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

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

Common Lispを頑張る(3)

台風、怖かったですね。関東に住んでるんで風が強いぐらいでしたが。
一日空きましたが、やっていきます。
「Land of Lisp」3章、構文の話です。

Lispシンタックス

C++などの難解な言語に比べて、Lispの書き方はシンプルなものだそうです。
括弧を使ってコードをリストにする。それだけだと書いてあります。

そしてリストの中に入るのは、大体下記のものたち。
・シンボル
 最も基本的なデータ型。アルファベット、数字、記号で構成されます。
 大文字小文字を区別しません。
・数値
 小数点が入っていれば浮動小数点数、そうじゃなきゃ整数として判断されるそうです。
 でかい数字でもLispは問題なく扱えると自慢げに書いてありましたが、
 訳注で「他の言語も最近はそれぐらいなら扱える」とある通り、
 C++でも53の53乗は問題なくできました。
 でも指数とかを使わずにドバっと出してくるLispはなんだか頼もしいです。
 どっちが読みやすいかは置いておいて。
・文字列
 厳密には基本的なデータ型とは言えないらしいです。
 でも皆よく使うよね、とのこと。異論ありません。
 文字の並びをダブルクォートで囲えば文字列。わかりやすいです。
 エスケープ文字を置くこともでき、エスケープしたい文字の前にバックスラッシュを置くと。

コードとデータの区別

Common Lispはコードを読む際に二つのモードを持っていて、
それはコードモードとデータモードだそうです。
・コードモード
 Lispのコードはリストの形で書かれますが、どんなリストでも良いわけではなく
 フォームと呼ばれる形になっていなくてはいけないそうです。
 そしてフォームとは、リストの最初の要素がコマンドになっているリストだと。
 そして、残りの要素は全て引数としてコマンドに渡されるという流れ。

[1]>
(- 20 (+ 9 4))
7
[2]>

とはいっても、最初の要素を読んでコードモードが終わりというわけではなく、
まず全体をコードモードで読むそうです。
上の例で言えば、コードモードでコマンド(-)を見つけ、
そのまま引数の20を見つけ、またフォームになっている要素を見つけて実行、
外のフォームに13を渡して-を実行し7を最終的に出すという流れのようです。
・データモード
 データモードで書かれたものをLispは実行しようとしないそうです。
 文字列を実行されたら困りますものね。
 データモードだとLispに教える方法はシンプルで、
 リストの前にシングルクォートを置くだけ。

[2]>
'(- 20 (+ 9 4))
(- 20 (+ 9 4))
[3]>

 さっき実行してくれた式も、クオートを置くだけでただのデータになってしまったようです。
 うーむ、シンプルだ...。

コンスセル

Lispのリストはコンスセルというもので繋ぎ合わされているそうです。
というか、コンスセルの連なりがリストに見えている、といった感じ。

コンスセルは、2つのくっついた箱だと説明されています。
それぞれの箱の中には別のコンスセルやデータを入れることができると。
ここまでの説明を踏まえて、'(1 2 3)というリストは下記のように解釈されます。
コンスセルの1つ目:1
コンスセルの2つ目:2 3
コンスセルの2つ目の1つ目:2
コンスセルの2つ目の2つ目:3
コンスセルの2つ目の2つ目の1つ目:3
コンスセルの2つ目の2つ目の2つ目;nil

説明を踏まえて、と言いながらnilとかいうのを出してしまいました。
nilがリストの終端を表すものだそうです。

リストを扱う関数

そんなLispの大事なリストを扱う主な関数は3つあるそうです。
cons、car、cdrという3つです。

consは2つのデータを結びつけて1つのコンスセルにする関数のようです。

[5]> (cons 'cat 'human)
(CAT . HUMAN)
[6]>

この、要素と要素の間にドットが置かれたものがコンスセルだそうです。
ただし、右側の要素としてnilを渡した場合は要素1つのリストを返してくると。

[9]> (cons 'cat nil)
(CAT)
[10]>

そして、空のリストはnilとして解釈されるそうです。

[10]> (cons 'cat ())
(CAT)
[11]>

また、リストはコンスセルの繋がりなのだからconsを使って
複数の要素からなるリストを作ることもできます。

[11]> (cons 'cat (cons 'human (cons 'dog nil)))
(CAT HUMAN DOG)
[12]>

Lisperはconsを使うことを「コンスする」ということがあるそうです。
さらっと日常会話に挟んだりしたいですね。「これとあれ、コンスしといて」。

carはセルの最初のスロットにある要素を取り出すのに使う関数だそうです。

[12]> (car '(cat human dog))
CAT
[13]>

cdrはその反対、2つ目の要素を取り出すのに使われます。

[13]> (cdr '(cat human dog))
(HUMAN DOG)
[14]>

2つ目の要素、すなわち最初以外ですね。

carとcdrを繋げた、cadrとかcdarとかcadadrとかもあるとか。
始めがc、終わりがr、あいだはaかdですね。とりあえず試します。

[18]> (cadr '(cat human dog pig cow monkey))
HUMAN
[19]> (caddr '(cat human dog pig cow monkey))
DOG
[20]> (cadadr '(cat human dog pig cow monkey))

*** - CADADR: HUMAN is not a list
The following restarts are available:
ABORT          :R1      Abort main loop
Break 1 [21]>

雑にやりすぎて怒られてしまいましたが、
例えば、caddrだったら、cdr→cdr→carという順番で取り出されてそうだとわかりました。
最後は'humanに無理な操作をしようとして怒られたみたいですね。

あと、リストを作るための関数も紹介されています。
その名もずばり、list関数。

[22]> (list 'cat 'human 'dog 'pig)
(CAT HUMAN DOG PIG)
[23]>

この章の残りはリストはネストできるとか、carとcdrの練習でした。

またまた長い上に駆け足で雑になってしまいましたが、今日はここまでです。