myfinderの技術や周辺的活動のblog

2009年8月31日月曜日

「実践Common Lisp」読書録

ある方から「実践Common Lisp」を譲っていただいた。
折角なので読書(写経)録をつけてみたい。

この本って、既に全部公開されてるものの訳本らしいすね。

Common Lispが一体なんなのかという話はここなどに任せておくとして、主に手を動かしてみた記録を晒します。
あ、ちなみに関数型言語は全然やったことないです><

1.Lisp処理系のインストール
要は実行環境の整備。
MacのCommon Lisp動作環境について調べてみたら、2ch評価でSBCLがよさげってな話らしいのでこれを採用したい。
(他にいいのがあったら教えてください><)

このサイトを参考にしつつ設定する。
ダウンロードしたパッケージを解凍してinstall.shを実行すればインストールできる、割と手軽。
その際にINSTALL_ROOT環境変数を設定するのを忘れずに。

その後sbclコマンドを打つと下記のようになる。

$ sbcl
This is SBCL 1.0.30, an implementation of ANSI Common Lisp.
More information about SBCL is available at .

SBCL is free software, provided as is, with absolutely no warranty.
It is mostly in the public domain; some portions are provided under
BSD-style licenses. See the CREDITS and COPYING files in the
distribution for more information.
*

これでとりあえず実行環境はできた。

2.Hello, World
sbclを起動すると、そのままLispプロンプトになるので、そこにプログラムを打てば実行される。

* "Hello, World"

"Hello, World"

こんな感じ。

3.関数
ただのHello, Worldしただけでは別に面白くも何ともないので、早速「文字列を標準出力に出力する」副作用を持ったコードを書いてみる。

* (format t "Hello, World")
Hello, World
NIL

formatというのは関数で、その後につく「t」と「出力対象の文字列」は必須らしい。
書式は下記の通り。

(format destination control-sequence arg 0 ... arg n )

今回の場合第一引数に「t」を指定したが、これは標準出力に出すもの。
出力結果の後の「NIL」が気になるが、これはformatを評価した結果をREPLが出力したもの。
「NIL」はLispにとっての「偽」と「null」である。

4.REPLって?
Lispプロンプトでは、シェルのようにコマンドを1行ずつ読み込んで解釈するのではなく、Lispの式を読み込み、評価し、その結果を出力する。それが終わるとまた次の式を入力できるようになる。
そういうサイクルを「read-eval-printループ」といい、縮めて「REPL」というそうだ。

5.REPLのサイクル
REPLの動作を簡単におさらいしてみる。

1: * 10
2: 10
3: *

1行目の「10」は最初に入力したもので、「reader」はこの「10」を読み取り、数値の10を表すLispオブジェクトを作成する。
このオブジェクトは「自己評価型のオブジェクト」といい、「evaluater(eval)」に与えられるとオブジェクト自身として評価される。
そのオブジェクトが「printer(print)」に渡され、2行目に「10」が表示され、3行目で次の入力を受け付けるというサイクルになっている。

6.関数の定義
Lispにおける関数の定義は「defun」という式を利用する。

* (defun hello-world () (format t "hello, world"))

HELLO-WORLD

「defun」のあとの「hello-world」が関数名。
関数名の次の「()」は引数リストだが、今回は引数を取らない関数なので空になる。
引数リストの次の括弧が関数の本体ということになる。
一旦関数を定義すれば、下記のように呼び出して利用できる。

* (hello-world)
hello, world
NIL


7.作業の保存
先ほど定義した関数はプロンプトを終わらせると消え去ってしまう。
もったいないので実行ファイルに書き出して、使えるようにしてみる。(参考サイト)

* (sb-ext:save-lisp-and-die "hello-world-bin" :executable t :toplevel 'hello-world)
[undoing binding stack and other enclosing state... done]
[saving current Lisp image into hello-world-bin:
writing 2784 bytes from the read-only space at 0x04000000
writing 1712 bytes from the static space at 0x04100000
writing 25530368 bytes from the dynamic space at 0x10000000
done]

ただこの手法、リンク先にも書いてある通りやたらとサイズがでかくなる。

$ ls -lha
total 50336
drwxr-xr-x 2 user staff 136B 9 1 01:00 .
drwxr-x--- 15 user staff 544B 9 1 00:55 ..
-rwxr-xr-x 1 user staff 25M 9 1 01:00 hello-world-bin
-rw-r--r-- 1 user staff 49B 9 1 00:56 hello-world.lisp

25MBとかどんだけ。。。実用じゃないすね。
誰かいい方法教えてください><

今日はとりあえずここまで。

0 件のコメント: