読者です 読者をやめる 読者になる 読者になる

kb84tkhrのブログ

何を書こうか考え中です

Scheme手習い (1) 掟

Scheme手習いの復習を兼ねて、お勉強ログを焼き直しながら書いていきます

第1章「おもちゃ」ではアトム・リストの基礎を覚えます

できることなら、読みながら例を試してほしい。

と書いてありますので実際に動かしながら進めましょう
以下のような問いを処理系で確かめるには

lのcarは何ですか。引数lは次の通り。

(a b c)

lのcarは何ですか。
ここで
lは ((a b c) x y z) です。

以下のようにします

> (define l '(a b c))
> (car l)
a

> (define l '((a b c) x y z))
> (car l)
(a b c)

lを2回defineしてますが、REPL上ではエラーになりませんでした
考えてみると不思議なことです
処理系に依存してるのかもしれません

きちんとやるとすると、(この本には出てきませんが)letを使ってこんな風に
書けば間違いなさそうです

> (let ((l '(a b c)))
    (car l))
a

> (let ((l '((a b c) x y z)))
    (car l))
(a b c)

上記ふたつは文章を直訳した感じですが
めんどうですので実際にはクォートしてこんな風に試します

> (car '(a b c))
a

> (car '((a b c) x y z))
(a b c)

読んでいくと5つの「掟」というのが出てきます
これはそれぞれcar、cdr、cons、null?、eq?についてのお約束を述べたものです

  • 関数carは空でないリストに対してのみ定義される。
  • 関数cdrは空でないリストについてのみ定義される。空でないリストのcdrは常に別のリストになる。
  • 関数consは2つの引数を取る。consの第2引数はリストでなければならない。結果はリストとなる。
  • 関数null?はリストに対してのみ定義される。
  • 関数eq?は2つの引数を取る。どちらも数でないアトムでなければならない。

実際のSchemeよりも条件が厳しくなっています
より純粋であるべき姿に近づけたということでしょうか

それを除けば当たり前のことが書いてあるだけだろ!と思ってましたが
あらためて見てみるとリストを処理するための関数の構造はこれらの掟で
半分くらい決まってしまう気がします
意外とあなどれないんじゃないでしょうか