Shammer's Philosophy

My private adversaria

Lisp Symbol Hacking at 20120128

Symbol を作成する (make-symbol) という関数がある。これを使用すると以下のようになる。

? (make-symbol (string-upcase "my-symbol"))
#:MY-SYMBOL
?

よくわからない#:が付いた状態で Symbol が作成される。
また、以下のように同じ名前の Symbol は常に同一のオブジェクトを指しているはず、なのだが、

? (eq 'a 'a)
T
? (defparameter *symbol1* 'a)
*SYMBOL1*
? (defparameter *symbol2* 'a)
*SYMBOL2*
? (eq *symbol1* *symbol2*)
T
?

make-symbol で生成されたように #: で開始される Symbol に関してはそうではない。

? (defparameter *symbol1* (make-symbol "A"))
*SYMBOL1*
? (defparameter *symbol2* (make-symbol "A"))
*SYMBOL2*
? *symbol1*
#:A
? *symbol2*
#:A
? (eq *symbol1* *symbol2*)
NIL
?

これは謎の仕様だ。一体どういうことなのか・・・Symbol を作成するときに make-symbol は使用するな、ということか?だったらなぜこんな関数がある?
まあ、make-symbol の意図はわからないが、普通に defparameter や setf では、内部で

  1. Symbol を作成
  2. 作成した Symbol に値をバインド

ということをしているはず。setq は (set (quote $symbol) $value) の略だ。このときに作成されるシンボルは普通は #: というようにはしていないはず。してはいけない、ということはないけれども、自分で作成する Symbol にこんな面倒なプレフィックスなんかつけないのが一般的・・・なはず。だから、意識しなくても同じ名前の Symbol は同一メモリのデータを指すことになっている。これを敢えて #: で定義したら、きっと同じにならなくて混乱するはず。

? (defparameter #:symbol1 "This is a symbol1.")
#:SYMBOL1
? #:symbol1
> Error: Unbound variable: #:SYMBOL1
> While executing: CCL::TOPLEVEL-EVAL, in process Listener(4).
> Type cmd-/ to continue, cmd-. to abort, cmd-\ for a list of available restarts.
> If continued: Retry getting the value of #:SYMBOL1.
> Type :? for other options.
1 >

おっと、、、予想外の結果だ。定義したはずの #:symbol1 が Unbound variable だと。。。
value には "This is a symbol1." という文字列が入っていると思ったが。当然だが、#: がなければうまくいく。

? (defparameter symbol1 "This is a symbol1.")
SYMBOL1
? symbol1
"This is a symbol1."
?

うーん、、、#: で開始される Symbol はユーザー側からはアクセスさせたくない内部処理に必要な情報をバインドするとき用のものだったりするのだろうか。

? (set (quote #:symbol1) "This is a symbol1.")
"This is a symbol1."
? #:symbol1
> Error: Unbound variable: #:SYMBOL1
> While executing: CCL::TOPLEVEL-EVAL, in process Listener(4).
> Type cmd-/ to continue, cmd-. to abort, cmd-\ for a list of available restarts.
> If continued: Retry getting the value of #:SYMBOL1.
> Type :? for other options.
1 > q
? (eval #:symbol1)
> Error: Unbound variable: #:SYMBOL1
> While executing: CCL::CHEAP-EVAL-IN-ENVIRONMENT, in process Listener(4).
> Type cmd-/ to continue, cmd-. to abort, cmd-\ for a list of available restarts.
> If continued: Retry getting the value of #:SYMBOL1.
> Type :? for other options.
1 >

意図的に quote を使って LISP の中でも原始的と思える方法で値をバインドしてみたが、それでも #: で始まる Symbol にはアクセスできない。実際のところはわからないが、やっぱり今の自分の理解力では内部処理用の Symbol で make-symbol も内部処理でしか使用しないような曲者なんだとしか思えない。