シンボルって何よ?

Schemeをいじりはじめて1年くらいかな(つんどく期間を除いて)。
まだまだ分からないことだらけ。
その一つが、シンボル。


http://karetta.jp/book-node/gauche-hacks/023107で紹介されているFizzBuzzのソースコードだけど、ぼけーっと読んでて気づいたことがある。
このWebページのソースコードは、本のそれと少し異なっている。

;; Webのソースコード
(map
 (lambda (x) (cond ((= (modulo x 15) 0) "FizzBuzz")
                   ((= (modulo x 5) 0) "Buzz")
                   ((= (modulo x 3) 0) "Fizz")
                   (else x)))
 (iota 100 1))

;; 本のソースコード
 (map
  (lambda (x) (cond [(= (modulo x 15) 0) 'FizzBuzz]
                    [(= (modulo x 5) 0) 'Buzz]
                    [(= (modulo x 3) 0) 'Fizz]
                    [else x]))
  (iota 100 1))

こんな感じ。文字列か、シンボルかの違い。
なんで違うの?意味の上で、どういう違いがあるの?


The Little Schemerの最後の章で次のような手続きvalueを作った。(id:yagiey:20081107:1226069483)

gosh> (value '(car (quote (a b))))
a

こいつから考えていくと...
「car」、「a」、「b」はそれぞれ束縛された名前。
評価してしまえば何らかのオブジェクト(値だったり手続きだったり)になってしまう。


だけど、それらを評価せずに、名前のままソースコードに置いとく、ってことだよね。
これってどういう意味だろ。わけわからん。

gosh> (define Fizz 42)
Fizz
gosh> Fizz
42
gosh> 'Fizz
Fizz

ってのは、C言語の頭で考えると

int Fizz = 42;
printf("%d\n", Fizz);
printf(Fizzの変数名);  // できないけど

みたいな感じなのかな。
Cの方は、実行時に変数名を取り出してきて文字列にするとかできんし。
あと、シンボルの場合はそれが束縛されているかどうかはどうでも良いっぽい(一応defineしたけど)。
もちろんSchemeの方は画面に出力したいから評価しているわけじゃないから、printfとは等価なわけないけど。


つまり、シンボルって、メタプログラミング的なことをする場合に、よく出てくるんかな。
そういえば、手続きvalueもメタプログラミングだよね。


...で、結局シンボルってなんなの?(´;ω;`)

コメントを受けて

...ってなわけで、文字列はequal?が#tかつeq?が#fになるようなインスタンスは沢山あるけど、シンボルはequal?が#tならばeq?も#tになるっぽい。
そういえば、

単純なデータ型では、真偽値とシンボルのみ、eq?で確実に比較できることが保証されている。

いろいろな「等しさ」 - チキン煮込みチーズミックス4辛

って書いたけど、そういうことだったのかー。


っていうか、「Smalltalk は Lisp の影響を強く受けている」ってのは意外だなぁ。
Smalltalkをやる余裕は今は無いけど、いつかやってみたいな。