第4回 慢性的CL勉強会[予習]
第4回 慢性的CL勉強会@Lingr 8時だョ!全員集合の資料の一つである
「Common Lisp Pitfalls」
を読み終わったので適当にまとめておきます。
*全体として*
Common Lispの勘違いしやすい点のまとめ。
既に知ってることから全く知らないことまで色々書いてました。
以前の慢性的CL勉強会ででてきた話なんかもありました(defvarとか)。
とりあえず、私には内容よりも英語の方が難しい(笑)。
*疑問など*
* Destructive functions that you think would modify CDRs might modify CARs instead. (Eg, NREVERSE.)
nreverseなどは一見CDRを書き換えてるように見えるけど、
実はCARを書き換えてるかもしれないといったことが書いてるんですが、
CARの書換でどうやってnreverseするのか分かりません。
– read-from-string, write-string, write-line, parse-namestring
どれ一つとして知りません(泣)
名前から想像すると、read-from-stringは文字列をストリームとして開くのでしょうか。
– EQUAL compares both vectors and structs with EQ.
equalって個々の要素の比較にはeqlを使ってたきがするんですが、eqと書いてあります。
手元のCLtL2(日本語版)によると
『数と文字はeqlによる比較を行い、他の全てのデータオブジェクトにはeqによる比較を行う』
ということをX3J13で決議したと書いてありました。
全部eqlでいいと思うんですが、なんでこんなややこしいことになってるんでしょうか。
* Some Common lisp operators use EQ, rather than the usual EQL, in a way that cannot be overridden: CATCH, GET, GET-PROPERTIES, GETF, REMF, REMPROP, and THROW. See table 5-11 on p 5-57 of the standard.
エイゴワカラナイヨ。
* The following trick for intercepting all unwinds is not portable and might not be allowed at all: (tagbody (unwind-protect (do-some-stuff) ;; Intercept all unwinds, ha ha! (go where-I-say)) where-I-say ;; We always get here. (do-some-more-stuff)) Informally: once an unwind to a certain point has begun, it must always go at least that far. [See CLtL pages 189-192.] Similar tricks using THROW or RETURN-FROM suffer the same fate. I used GO above because I think that makes the intention clearer.
こんなコードを書くなというのは分かったけど、
何で駄目なのかの説明がいまいち分かりませんでした。
* Remember that there are "potential numbers" and that they are reserved tokens [CLtL pages 516-520]. Normally, only odd things such as 1.2.3 or 3^4/5 are "potnums", but when *READ-BASE* is greater than 10, many more tokens are effected. (For real fun, set your read base to 36.)
なにゆーてんの?
* You often have to declare the result type to get the most efficient arithmetic. Eg, (the fixnum (+ (the fixnum e1) (the fixnum e2))) rather than (+ (the fixnum e1) (the fixnum e2))
(the fixnum e1)って一体何?
型宣言をその場でやってるってことでしょうか。
– proclaim, declaim
熱い説明が書いてあるけど、
どっちも知りません(泣)
– packages
これも前提知識がないのでさっぱり分かりません。
なんか大きく仕様が変更したということだけ聞いたことがあります。
– CLOS
これも前提知識がないのでさっぱり。
Flavorの説明なら少々読んだことがあるんですけど。
そういえば、CLOSの読みは「クロス」だと思ってたんですけど、
先日ある方に、「京都では”シーロス”って読むんだよ」と教えてもらいました。
*感心したところ*
– (let ((x 5)) (eq x x)) might return false
最適化の関係でletが消えてxが5に置き換わると、
nilになる可能性があるそうです。
– flet ((f …)) (eq #’f #’f)) can return false.
#’を使うと新しいオブジェクトが生成されるので、
関数の比較を行うのは難しいとか。
(let ((x 1)) (declare (fixnum x)) (let ((x ...)) ;; This x must be a fixnum too! ...))
型宣言は変数(束縛)に対してではなく、名前に対して行われるため、
同じ名前で別の変数を作っても、宣言が有効になるらしいです。
ただし、これはCLtLの記述であり、ANSIでは変数に対して型宣言がなされ、
この場合は内側のxには型宣言は無視されるとか何とか。