空想犬猫記

※当日記では、犬も猫も空想も扱っておりません。(旧・エト記)

etolisp進捗(2)

etolispのlambda実装完了。しかし,どうやらシンボルとか関数とかの考え方がCommon Lispとは違っていることに気付く。後で気付くのは「仕様はこんなもんだろう」と我ながら適当に作ってるせいだ。私の実装はlambdaもbuilt-in関数も,単なるシンボルも,全て共通のValue型クラスを継承していて,先頭のconsのcarを asFunction() というコールで関数化して評価している。そして asFunction() を呼んでも実は関数じゃなかった,という場合には潔く runtime_error を投げるようにしている。しかし,Common Lisp では関数,シンボル,λ式は,明確に型が区別されている。そして先頭のconsのcarには,型の明らかな関数かλ式しか入れられないみたいだ。たとえば

( (lambda (x) (+ x x)) 1)
(setf func (lambda (x) (+ x x)))

と,出来るけど,funcはあくまでシンボルなので

(func 1)

と出来ない。そのかわり

(apply func '(1))
(funcall func 1)

とかしてやらねばならない。また,λ式と関数が同じと言えばそうではなくて]

(setf func (lambda (x) (+ x x)))

はいいけど

(setf func +)

はダメとか。でも

(setf func #'(lambda (x) (+ x x)))
(setf func #'+)

は両方ともOKとか。λ式の「#'」が状況に応じて省略出きるところが一貫していない。一方,etolispは上記の書き方を全て許してしまう。なんでもあり子さんだ。Common Lispは,quoteするのにも通常の「'」ではなく,関数専用の「#'」を使う必要がある。一方,etolispはquoteの種類を区別する必要がない。この辺の制約は,恐らく,Lispを直に最適化された機械語に翻訳したい場合に必要になるのだろう。私の目指すものはプログラムしやすい動的なアプリ組み込みようLLなので,なんでもあり子さんでいいかなと思っている。わざわざ動的言語のうまみを捨てるのも勿体ないし。でも coerce や compile をすると,むしろ遅くなったりするのか。いやだな…,何とか後で悪あがきしよう…。
次は制御系(if とか cond とか)をやった後,マクロ系を地道に作っていこうと思う。

そういえば本日,生身の人間から初めてトラックバックをいただいた。ありがとうございます。同じ穴のムジナは世の中に沢山いるようで*1。じつはLispの世界は星の数ほど処理系があって,処理系の数だけ方言があるのだ。私があらかじめ「他の処理系を参考にしない」と言ったのは「自分で考えて設計しながら楽しむ」というのも大きいが,一番の理由は「おそらく,他の処理系を見たらよく出来すぎていてやる気が失せるんだろうな〜」と思ったからである。
Lispの処理系を作ろう,とかいうと,親切な人は「NIH症候群」とか「車輪の再発見」という言葉を思い浮かべるかも知れない。けれども,私のモチベーションはどちらかというとプラモ作りに近いと思っている。それは,説明書通りに作り上げても,よくも悪くも世界に一つしかない作品になって,そして作った人には,次のプラモを作るスキルと自信を与える知的作業なのだ。…とまあ,無駄ばかりじゃないよと。あらかじめ冷たい目で見られないように予防線を張っておこう。
そういう意味ではLispは最高の教材だなと実感する。教育の現場でよく使われる理由も分かる。噂通り深い世界もまだまだありそうだし。
レッツリスプ。

*1:すいません