"Common Lisp: A Gentle Introduction to Symbolic Computation"を読んで自分の理解をまとめていく。
やっとよく見るコードの形で議論が進んでいくようだ。
Contents
EVAL notaition
今まではブロック図表記で考えてきたがEVALで評価できる書き方で考えていく。文字で書くと何やら難しいことを言っているようだが、要は(+ 1 2)はEVALで3と評価されるという話。
自分でコードを書く際はEVALと入力する必要はない、基本的には。
(+ 1 2) ; => 3
基本的な評価ルールは、
- 数値、文字列、
T、NILはそれ自身に評価される。 - リストは先頭要素を関数として評価し、残りの要素をその関数の引数とする。
- 引数も評価したうえで関数に渡される。
例えば(+ (+ 1 2) 4)は引数(+ 1 2)が3に評価され、その3と4が最初の+の引数として渡されるということ。 - シンボルはシンボルが指している変数の値へと評価される。
- シンボルやリストを評価せずデータとして扱うためにはquote
'(シングルクォート)する。
いろいろevalしてみる
+, -, *, /
特に悩むところはなし。引数は左側から評価されていく。
(+ 1 2) ; => 3 (+ 1 2 3 4 5) ; => 15 (- 1 2) ; => -1 (- 1 2 3 4 5) ; => -13 (* 1 2) ; => 2 (* 1 2 3 4 5) ; => 120 (/ 1 2) ; => 1/2 (/ 1 2 3 4 5) ; => 1/120
ABS, SQRT
これも特に悩むところはなし。
SQRTは返り値は整数ではなく浮動小数点のようだ。負の値を入れても複素数で返してくる。複素数をプログラム中で使う方法はまた後日考えよう。
(abs 100) ; => 100 (abs -100) ; => 100 (sqrt 100) ; => 10.0 (sqrt -100) ; => #C(0.0 10.0)
Predicates
例えばnumberp。
(numberp 10) ; => T (numberp a) ; => ERROR! (numberp 'a) ; => NIL
先に述べたように引数も評価されてから関数に渡される。2行目のようにaをクォートしないと評価しようとしてエラーとなる。(まだシンボルaになにも束縛していないためUNBOUND-VARIABLEとなる。)
ほかのPredicatesも特に悩むところはない。
リストの評価
先に述べたようにリストは基本的には一つ目の要素を関数、残りを引数として評価されてしまう。ただのデータとしてリストを扱うには上でシンボルをクォートしたようにリストもクォートする必要がある。
(a b c d) ; => ERROR!
'(a b c d) ; => (A B C D)
('a 'b 'c 'd) ; => ERROR!
(list 'a 'b 'c 'd) ; => (A B C D)
1行目はaというfunctionはないというエラーになる。3行目も'aというfunctionはないというエラーになる。自分の環境ではvlimeのREPLで'(a b c d)を上記のようには評価できずエラーとなった。sbclのREPLに打ち込んだ場合は上記通り動いていた。今のところ理由はわからない。
上記を踏まえて(a b c d)から一つ目の要素を取り出す場合は、
(first '(a b c d)) ; => A
のようにクォートする。
まとめ
- 数値、文字列、
T、NILはそれ自身に評価される。 - リストは一つ目の要素を関数、残りを引数として評価される。
- シンボルは束縛されている値、関数に評価される。
- 束縛されていないシンボルを評価しようとするとエラー
- リスト、シンボルを評価せずデータとして渡すためにはクォート
'する。
補足
"Common Lisp: A Gentle Introduction to Symbolic Computation"ではシンボルに対して束縛(bounded)という言葉を使うのは正しくないと言っているようだ。。束縛されるのはシンボルが参照している変数(variable)だとということなのだろうか。

コメント