プログラミングを頑張る日記

プログラミングを勉強して、ハッカーになろう

Common Lispを頑張る(50)

amazon primeで観れるシリコンバレーが面白いです。
おもわずCommon Lispよりもそちらの話をしたくなってしまうぐらいですが、
それは抑えて、「実践Common Lisp」をやります。

There is no List.

リストってなんでしょう。もはや哲学的な問いのようです。
リストを理解する手掛かりは、そのほとんどがより基本的なデータ型のインスタンスである
オブジェクトの上に構築された幻想だと理解することにあるそうです。
その単純なオブジェクトとはコンスセルと呼ばれる値のペアであり、consにより作られます。

consは2つの引数をとり、その2つの値を保持する新しいコンスセルを返します。
2つ目の値がnilか他のコンスセル以外なら、ドット対(ドットペア、ドットリスト)を返します。

CL-USER> (cons 1 nil)
(1)
CL-USER> (cons 1 '(2 3))
(1 2 3)
CL-USER> (cons 1 2)
(1 . 2)
CL-USER>

コンスセルに含まれる2つの値は、それぞれcarとcdrと呼ばれます。どちらともsetf可能な場所です。
コンスセルに含まれる値はどんな種類のオブジェクトでも良く、
コンスセルを繋ぎあわせ巨大な構造を作れます。
この仕組みはLisp固有のものではなく、単方向リンクリストと呼ばれていますが、
Lisp族以外でこの簡素なデータ型に広範なサポートを与えているものがほぼ存在しないのも事実なよう。

うむむ...まあ色々書いてありますが結論、リストはコンスセルあるいはnilへの参照であると。
あ、あと木構造を表わすのに便利。

関数型プログラミングとリスト

関数型プログラミングとは、副作用がないことです(あってますよね)。
で、その利点はプログラムの理解が容易になること。

さて。数値は不変なオブジェクトなので、それを扱う関数は当然関数的になります。
それに対してリストはcarやcdrへのsetfで変化しえます。
とはいえ。含まれている要素によって値が決まるという考えをすれば、リストも関数的データ型と言えると。
うむむ。まあ、そうでしょうな。しかしその理屈で言うとほとんど関数的データ型では。
そうでもないのかな。わからん。とりあえず納得したことにします。

Common Lispのリスト操作関数のほとんどは関数的に書かれているそうです。
その理由は、与えられた引数とコンスセルを共有する結果が返せるようになるから。

CL-USER> (append '(1 2) '(3 4))
(1 2 3 4)
CL-USER>

上でappendの最終的な仕事は、(1 2 3 4)というリストを返すことです。
もちろんその4つのコンスセルを含むリストを作ってもいいのですが、そこまでせずとも、
1と2をそれぞれ含むコンスセルを2つ作り、2つめのコンスセルのcdrが
2つめの引数の(3 4)を指すようにすれば楽です。

へぇ~、って感じの話でした。とはいえちょっとびっくりしたので今日はここまで。
本当は早くシリコンバレー視聴に戻りたいのでした。