実践CommonLispを読むその1

Lispを勉強するとプログラミングの手筋がよくなると聞いた。Lisperはエスパーと同じくらい凄い人種だとも聞いた。物凄く興味があるので勉強してみる事にする。くじけず、諦めずゆっくりとやっていければと思う。

第一章 序論:なぜLispなのか?

Lispって現在どこかで利用されているの?利用されているって書いてあるんだが、私の周りでは誰も利用していない。Lispすら知らない人もいる。そんな言語を学ぶ必要性があるのだろうかと思いつつ興味があるので本をとってみたんだけどね。まあいいや。

第二章 お気の済むまで:REPLツアー

REPLってなに?
飛ばし飛ばしに読んでいるから読み飛ばした可能性があるね。

REPL:read-eval-printループの事、読み取り(read)、評価(eval)、印字(print)を繰り返す

処理系には私は「CLISP」を使う。本書では「Lisp in Box」を使っているが同じCommonLispの処理系なので問題ないだろ。多分。

CLISP:http://clisp.cons.org/

最初のプログラム、「hello, world」

[0]> "hello, world"
"hello, world"
1.ダブルクォートで囲まれた文字列を読み込むと読取機は文字列オブジェクトを構築する。
2.ダブルクォートは文字列オブジェクトに含まれない。
3.印字の際、印字機がダブルクォートをつける。

ただ、これだとプログラムとは違う気がする。

[0]> (format t "hello, world")
hello, world
NIL

少しプログラムらしくなった。

NIL:FORMAT式を評価した結果をREPLが印字したもの
FORMAT式の副作用:標準出力に印字する

ちょっと不思議ですね。私の知っているプログラムであれば標準出力に印字する事がメインな処理だと思う関数を作ったりするのだが、副作用なんですね。

FORMAT式を評価した結果がNILで副作用により標準出力に印字したって事。

なんだか奇妙だ。
関数を使った「hello, world」

[0]> (defun hello-world()(format t "hello, world"))
HELLO-WORLD
[1]> (hello-world)
hello, world
NIL
defun
戻り値:定義した関数名(上記ではHELLO-WORLD:なぜか大文字)
副作用:関数を作成するって事?

多少、プログラミングっぽくなった。Lispって副作用の方が重要なのかな。あとFORMAT式の「t」ってなんだよ。あとあと出てくるようだからあまり調べない。

あああああ、作業を保存したりするやり方がCLISPではわからないよ〜仕方ないので調べる事にする。本書と処理系をあわせておくべきだったか、悩むね。

CLISPでは直接インタプリタからファイルに保存はできないみたい。定義した関数をテキストに保存して呼び出す。見たいな事をする。ちょっとめんどくさいね。本書の処理系と比べると面倒だが、まあ我慢するさ。

; hello-world.lisp
(defun hello-world()
    (format t "Hello, world!"))

ちなみに「;」はコメント。末行まで有効

[0]> (load "hello-world")
;; Loading file ・・・
;; Loaded file ・・・
T
[1]> (hello-world)
Hello, world!
NIL

「T」は正しくロードされたって事を表す。

参考にしたWEB:http://www.sakalab.org/clisp/clisp.html
上記ページにはそれ以外にも参考になるものが沢山ありました。

「trace」あまり意味なかった

[3]> (trace hello-world)
;; Tracing function HELLO-WORLD.
(HELLO-WORLD)
[4]> (untrace hello-world)
(HELLO-WORLD)

ちなみに、「trace」は「untrace」するまで続きます。更にちなみに「trace」を行うのは指定された関数だけです。それ以外の関数は普通に動いています。トレースされません。

「time」ベンチマーク

[5]> (time (hello-world))
2. Trace: (HELLO-WORLD)
Hello, world!
2. Trace: HELLO-WORLD ==> NIL
Real time: 1.88E-4 sec.
Run time: 0.0 sec.
Space: 1976 Bytes
NIL

「load」にはもう一種類あって「compile-file」を利用する方法。読み込むファイルをコンパイルしてロードするって方法ですね。コンパイルする事によって多少速度が向上するみたいです。また、その際、「.fas」と言ったファイルを作成します。

[1]> (load (compile-file "hello-world"))
;; Compiling file /home/vmplanet/work/lisp/hello-world.lisp ...
;; Wrote file /home/vmplanet/work/lisp/hello-world.fas
0 errors, 0 warnings
;; Loading file /home/vmplanet/work/lisp/hello-world.fas ...
;; Loaded file /home/vmplanet/work/lisp/hello-world.fas
T

「hello-world.fas」の中身を見てみた。バイナリかと思ったがテキストだった。

(|SYSTEM|::|VERSION| '(20060802.))
#0Y |CHARSET|::|UTF-8|
#Y(#:|1 2 (DEFUN HELLO-WORLD NIL ...)-1|
   #20Y(00 00 00 00 00 00 00 00 00 01 DA 2F 01 DA DC 32 83 C5 19 01)
   (|COMMON-LISP-USER|::|HELLO-WORLD| |SYSTEM|::|REMOVE-OLD-DEFINITIONS|
    #Y(|COMMON-LISP-USER|::|HELLO-WORLD|
       #18Y(00 00 00 00 00 00 00 00 06 01 DA 6B 01 33 01 15 19 01)
       (#Y(|COMMON-LISP-USER|::|HELLO-WORLD-1|
           #19Y(00 00 00 00 01 00 00 00 01 17 DA AF 38 02 31 8B 9E 19 03)
           ("Hello, world!")
           (|COMMON-LISP|::|T| |COMMON-LISP|::|T| |COMMON-LISP|::|T|))
        |COMMON-LISP|::|*STANDARD-OUTPUT*|)
       (|COMMON-LISP|::|T| |COMMON-LISP|::|T| |COMMON-LISP|::|T|) ()
       |COMMON-LISP|::|NIL|))
   (|COMMON-LISP|::|T| |COMMON-LISP|::|T| |COMMON-LISP|::|T|))

まったく理解不能なんだが・・・分かる日が来るのかな?それとも理解する必要はないのかな。多分、16進の数値がならんでいるのところが機械語に変換されたコードなんだと思う。それ以外はまったく分かりません。

次に「hello-world.lib」ってファイルも存在していた。いつ作成されたのか分からないが中をのぞいてみた。

#0Y |CHARSET|::|UTF-8|
(|SYSTEM|::|C-DEFUN| '|COMMON-LISP-USER|::|HELLO-WORLD|
 (|SYSTEM|::|LAMBDA-LIST-TO-SIGNATURE| '|COMMON-LISP|::|NIL|))

わからないね。まあいいや、次ぎいこ〜