言語ゲーム

とあるエンジニアが嘘ばかり書く日記

Twitter: @propella

Common lisp で遊ぶ

なぜかいつも世間から半周以上遅れて興味が沸いてくるのだけど、突然 Common lisp をやってみた。処理系は沢山あって迷うがとりあえず cygwin でインストールが簡単だった clisp http://clisp.cons.org/ マークがユダヤ教の蝋燭立てみたいなのはカッコの対応を表しているのだろうか?emacs (meadow) から簡単に使えるように

と設定してから、

で実行。インタプリタが起動する。素晴らしく設定が簡単だ!一行ずつ式を評価出来るほか、emacs lisp を実行するように式の好きな部分で M-x M-e (lisp-eval-last-sexp) 出来る。ただ、readline の補完が効く分ターミナルから実行した方が便利。

さて、common lisp の面白い所は scheme と違って同じ名前の変数と関数が定義出来る所。最初はダサイ!と思ったけど、結構面白いのでは?

> (defun triple (x) (* x 3))
TRIPLE
> (setq triple 3)
3
> (triple triple)
9

これを javascript に意訳するとこうなる

> triple = new Object()
[object Object]
> triple.symbol_function = function (x) {return x * 3}
function ...
> triple.symbol_value = 3
3
> triple.symbol_function(triple.symbol_value)
9

つまり、common lisp では、triple というシンボル(名前)に関数の入れ物と値の入れ物があるという事らしい。入れ物の事をセルと言って、特別な関数で引き出す事が出来る。例えば関数の本体は symbol-function または #' で取り出す。

> (symbol-function 'triple)
#<FUNCTION TRIPLE (X) (DECLARE (SYSTEM::IN-DEFUN TRIPLE))
  (BLOCK TRIPLE (* X 3))>
> #'triple
#<FUNCTION TRIPLE (X) (DECLARE (SYSTEM::IN-DEFUN TRIPLE))
  (BLOCK TRIPLE (* X 3))>
> (symbol-value 'triple)
3

common lisp では、関数呼び出しをする時 (関数名 引数 ...) という記法を使うが、その意味は、「関数名から関数を取り出して呼び出す」いう意味だ。関数の実体を直接実行するには apply を使う。これはださい。

(apply #'triple '(3))
> 9

セルには、Name, Package, Property list, Value, Function という種類がある。このうち、Property list というのが面白くて、勝手に好きな値を置いておく事が出来る。

> (setf (get 'triple 'hello) "world")
"world"
> (get 'triple 'hello)
"world"
> (symbol-plist 'triple)
(HELLO "world" SYSTEM::DEFINITION
 ((DEFUN TRIPLE (X) (* X 3)) .
  #(NIL NIL NIL NIL ((DECLARATION OPTIMIZE DECLARATION)))))

このように、setf を使うとシンボルのプロパティに別のオブジェクトを保存出来る。しかし、setf の文法が非常に黒魔術的で不快だ。なぜ普通に (pset 'triple 'hello "world) とかじゃ駄目なのかな?lisp では関数の評価前に引数が評価されるというのがルールなのだが、setf はマクロなのでこういう事が出来るらしい。けどマクロかどうかいちいち気にするのは嫌だな。