Schemeのお勉強 その1

amazonプログラミングGaucheを注文して、届くまではこちらscheme独習中。

シンボル

シンボル。schemeでは大文字小文字区別無しらしいけど。

gosh> (eqv? 'ABC 'abc)
#f
gosh> (eqv? 'ABC 'ABC)
#t

gaucheでは区別するみたい。リファレンスみたらそう書いてあった。

文字・文字コード変換

gosh> (char->integer #\a)
97
gosh> (integer->char 97)
#\a
gosh> (char->integer #\あ)
12354
gosh> (integer->char 12354)
#\あ

日本語もOK。ユニコードです。

index によるアクセスは XXXX-ref

gosh> (string-ref "あいうえお" 1)
#\い
gosh> (list-ref '(1 2 3 4) 1)
2
gosh> (vector-ref #(9 8 7) 1)
8

ドット対はリストじゃない。空リストは null?で判定。

gosh> (pair? '(1 . 2))
#t
gosh> (list? '(1 . 2))
#f
gosh> (list? '(1 2))
#t
gosh> (null? ())
#t

そういえば commonLisp の nil に該当する定数は schemeには無いの? いまのところ出てきて無いぞ。
commonLisp では 真偽を t/nil で表現してたが、scheme では #t/#f だね。じゃあ nil = #f ってことになるのかな? うーん。

listと述語

 この項、ツッコミをいただいたので書き直しです。lispの基本、リストについて整理。
(list? '(1 . 2)) => #f から、「ドット対はリストじゃない」と書いたことに対して。

buzztaikiさんのツッコミ
cdr が cons-cell な cons-cell は list ですよ。
(list? '(1 . (2 . 3))) => #t
(list? '(1 . (2 3))) => #t
(pair? '(1 2)) => #t

 リストは cons-cell が繋がったもの。この基本を忘れてました。'(1 . 2)というドット対は、ただ一つの cons-cell なのでリストでは無いんですね。
あと cons のことを pair と呼ぶことを知りませんでした。ドット「対」という言い方は知ってましたが……。
'(1) のような単一要素のリストは、 '(1 . ()) と考えれば、cdr に空要素を持つのconsが繋がってるとみなせそう。(ちょっと苦しい?)

#t と #f と '()

commonLisp の nil を引き合いに出したことに対して、解説もいただきました。

SaitoAtsushiさんのコメント
#tや#fは真偽値を表現する値であり、空リストとは違う型です。 (if '() 1 2) とでもしてみれば 1 が返ることが確認できます。 #f 以外は真と解釈されます。
CommonLisp の nil は空リストと偽値を兼任していますが、 Scheme ではそれぞれ違うものなわけです。 Scheme 的な潔癖さを考えれば if の第一引数は真偽値に限定してもよさそうなものですが、そこらへんは利用上の便宜と歴史的な経緯なのでしょう。

 私の lisp 原体験は xyzzy での commonLisp だったんですが、最初ブール値の表現が「T or F」でなく「T or NIL」であることに違和感を感じました。そういう意味では、schemeの真偽値はこれ以上無いくらい分かりやすいものといえますね。私の方がいつの間にかcommonLisp的な方式に染まっていたようです。多分pythonを頑張って習得したのも原因のひとつかもしれません。pythonじゃ、ブーリアンのFalse以外に、空list, 空tuple, 空辞書, 空文字列, None, そして 0 も、おおよそ「値が無い」物は皆、偽扱いですから……。

ちなみに (null? ()) という書き方は現在の Gauche では許容されますが、 Scheme 的には誤りです。(null? '()) という風に quote を付けるべきです。

 quoteするかしないか迷ったところでした。試してみてたまたま通ってしまったので省略してしまいました。
 貴重な突っ込みありがとうございました。勉強になります。

以上、ツッコミによる修正箇所はここまで。

プロシージャじゃなくサブルーチン(?)

schemeでは cons は らしいけど、gaucheだと……。

gosh> cons
#<subr cons>
gosh> +
#<subr +>
gosh> display
#<subr display>
gosh> do
#<syntax do>
gosh> if
#<syntax if>
gosh> dolist
#<macro dolist>

は多分サブルーチンかな。いわゆる「特殊形式」ってのはになるのかな?

ポート

解説によると標準入出力は「ポート」というデータ型に属するらしい。
current-output-port で現在の出力先が分かる。

gosh> current-output-port
#<subr current-output-port>
gosh> (current-output-port)
#<oport (stdout) 0x107f6ee0>