実践CommonLispを読むその2

第三章 実践:簡単なデータベース

ここではCDの情報を登録するアプリを通してLISPを学んでいくようです。最初データベースと見て、OracleMySQLPostgreSQLを思い浮かべた私は先走りすぎていたようですね。当然のようにテキストベースのDBでした。少し残念です。LISPってOracle等のDBにアクセスできるの?できなければ実用に耐えられないよね。

; LIST関数:リストを作成する
[0]> (list 1 2 3)
(1 2 3)
[1]> (list :a 1 :b 2 :c 3)
(:A 1 :B 2 :C 3)

(:A 1 :B 2 :C 3)はハッシュと考えた方が理解しやすいよね。LISPでは本物のハッシュではないらしいんだが理解のしやすさから今はハッシュと覚えておく。

ハッシュから値を取り出すには

[0]> (getf (list :a 9 :b 8 :c 7) :c)
7
(dolist (cd *db*)
  (format t "~a:~10t~a~%" cd))

意味が分からなかった。

dolistマクロ

マクロだそうだ。関数とマクロ、厳密に異なるようですね。理解していないけど、「*db*」はグローバル変数LISPの慣習に従うとグローバルな値は「*」で囲む。でこれは、PHPPerlのforeachと似た動きをする。リストから先頭の値を取得して変数「cd」に格納し処理を続ける。NILが返ってくるまでやるんでしょうね。

  (format t "~{~a:~10t~a~}~%" cd)

「t」は標準出力。他の値に変更したら動かなかった。「*standard-output*」 の代替表現。先頭「~」の文字列は指示子を示す。C言語でのprintf関数で利用する「%」と聞いて理解できた。「~{ … ~}」でリストの中身を頭から呼び出しNILが帰ってくるまで実行する。感覚で理解できるんだが上手く説明できない。残念な子です。

PARSE-INTEGER関数

数値を返す。文字列に数値が含まれていない場合、またはゴミが混じっていたらエラーを通知する。処理が止まってしまうので美しくないと、PARSE-INTEGER関数の動作を変えるため、「:junk-allowed」キーワードに「t」をセットするとエラーは発生しなくなる。ゴミ許可しますをTRUEに設定って感じかな。

更にPARSE-INTEGERがNILを返してきたらOR関数で処理をする

  (or (parse-integer (・・・) :junk-allowed t) 0)

とすると、NILが返ってきてら最終的に0を返すようになる。

Y-OR-N-P関数

先頭が「y」「Y」「n」「N」で始まらない文字で入力するとユーザに再度入力を促す

[1]> (y-or-n-p "Install")
Install (y/n)
Please answer with y or n : aaa
Please answer with y or n : 123
Please answer with y or n : y
T
[2]> (y-or-n-p "Install")
Install (y/n) n
NIL

「y」を選択すると「T」が返ってきて「n」を選択すると「NIL」が返ってくる。本には「(y-or-n-p "Install [y/n]: ")」と書いてあったが処理系の違いか、勝手に「(y/n)」を付けてくれるみたい。ちなみに「y-or-n-p」の「p」ってなんだろうね。


3章を軽く読んだんだが、途中からわけが分からなくなったよ。もう一度しっかり読み直すつもり。ただLISPって今までやってきた言語とは毛色が違う気がする。今までは全体を捉えて、その後、細部を詰めながら実装してきたんだが、LISPって最初に部品を造って、それを大きくしていく感じ。何を造るかってのをつめたら、そのものを造るのに必要な部品は何が必要かを見極めてコーディングする感じかなとふと思った。実際はどのように考えて実装していくのか、慣れだよね。

ではでは