Hatena::Groupcadr

わだばLisperになる このページをアンテナに追加 RSSフィード

2004 | 12 |
2005 | 01 | 02 | 07 | 10 | 11 |
2006 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2007 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2008 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2009 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2010 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2011 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 11 |

2007-12-04

Practical Common Lisp (2)

| 03:42 | Practical Common Lisp (2) - わだばLisperになる を含むブックマーク はてなブックマーク - Practical Common Lisp (2) - わだばLisperになる

ひき続きPractical Common Lispを読んでみます。

2. Lather, Rinse, Repeat: A Tour of the REPL

Common Lispの開発環境についての説明。

Matthew Danish氏とMikel Evins氏が作っている「Lisp in a Box」について。

「Lisp in a Box」というのは、Emacsエディタと、その上でCommon Lisp処理系と連動して動作するSLIMEという強力な開発環境をセットにしたもの。

このセットはCommon Lispの開発スタイルの特徴である、高度に対話的で、インクリメンタルな開発というのを十分に洗練された方法で提供してくれる。

SLIMEはどのOSや、ベースとなるCommon Lispの処理系を選んでも、インターフェースは統一されているので、その違いをあまり意識することなく使うことができる。

商用的なベンダーが提供しているGUIのIDEもあるけど、Common Lispの基本的なことを修得する、という目的には、ちょっとややこしい嫌いがあるので、「Lisp in a Box」がお勧め。

Choosing a Lisp Implementation

とりあえず、ベースとなるCommon Lispの処理系を選ぶ。

処理系の選択というと、Perl, Python, Visual Basic (VB), C#, Javaに馴染み深い人からすると、ちょっと不思議に思うかもしれない。

Common LispはANSIで規格が策定されていて、ANSI Common Lispといえば、それに則って開発された処理系のことになる。

特定のベンダーが提供する処理系が言語の標準実装だったり、特定の実装が唯一の処理系だったりするのとはちょっと違う。

というわけで、ANSI規格に則ったプログラムかを確認していれば他の処理系でも動く。

でも、その一方で、プログラムで処理したいことが全部の規格の範疇に納まってるとは限らない。

そういうプログラムでもできるだけ、移植性の高いものにしたい。

Common Lispでは、そういう処理系の差異を吸収するような柔軟な仕組みもあるので、後の章でそれを解説する。

さて、処理系の選択だけど、メインで使ってるOSが何かってことに一番左右されるんじゃないだろうか。

商用のANSI Common Lisp処理系であるAllegro Common Lispが使いたいって場合には、Linux, Windows, とOS X用が使える。

この本の内容を実行するということであれば試用版Allegro Common Lispが使える。

オープンソースの処理系が良い、ということであれば、選択肢はいくつかあって、SBCLという性能の良い処理系が使える。

SBCLは、CMUのCMU Common Lispをベースに開発されたもの。

CMU Common Lispそれ自体も良い選択だと思う。けれど、SBCLがよりインストールが簡単で、21-bitユニコードをサポートしている。

Mac OSXを使ってるということであれば、OpenMCLが良い選択だと思う。コンパイラはネイティブなマシンコードを出力するし、スレッドもサポートしている。おまけに、Carbonや、Cocoaのインターフェイスも整備されている。OpenMCLには、商用、オープンソースの両方がある。

この本のCommon Lispのコードは、どの処理系を選んでも問題なく動く筈のものを載せている。そうじゃない場合は断り書きを書く。

また、SLIMEは、処理系の違いを吸収してくれる筈。

Common Lispの処理系の出力は、GNU/Linuxで動く、Allegroのものを使った。エラー表示や、デバッガへ入った表示だけど、これは処理系によって結構違う表示になることがある。

Getting Up and Running with Lisp in a Box

始めてのLisp in a Boxのセットアップを最小限の手間で完了させるには、自分が選択したOSやそのOSで使える処理系を良く吟味する必要がある。

これらの選択については、32章で解説している。

Lisp in a Boxでは、Emacsをメインのエディタとして使うが、ちょっとしたEmacsの使い方を知っておく必要がある。

〜Emacsの基本的な使い方についての説明が続く〜

SLIME:C-c C-z
 REPLバッファにカーソルを移動する。

Free Your Mind: Interactive Programming

さて、Lisp in a Boxを起動して最初に目にするものは、

CL-USER>

というプロンプト。

これは、DOSとか、Unixシェルのプロンプトと同じで、入力を受けつけていて、入力→実行というサイクルを繰り返す。

read-eval-print loopとか、略してREPLと呼ばれる。

top-levelとかthe top-level listenerとかthe Lisp listenerとも呼ばれる。

このREPLに式を読み込ませて実行していくことになる。

実際とのところは、エディタ内に読み込まれたファイルの内容を対話的に評価する便利な仕組があるので、いちいちこのREPLにコピペして実行という訳ではない。

Experimenting in the REPL

REPLを使ってみる。まずは、"10"を入力して、Returnを押してみる。

CL-USER> 10
10

REPLという言葉に照らし合せるなら、

CL-USER> 10 ;READ(REPLのR)
10          ;EVAL-PRINT(EしてR)

ってことになる。

"10"はself-evaluatingオブジェクトといってそれ自身が既に結果となっているオブジェクト。

次に、(+ 2 3)を実行してみよう。

CL-USER> (+ 2 3)
5

括弧に囲まれたものは全部、リストと呼ばれる。

この場合は、+、2、3の3つがリストの内容。

リスト先頭は、特別扱いされて関数の名前という扱いになる。そしてそれ以降は、その関数の引数。

つまり引数2と3が、+という関数に渡されることになる。

しかし、こんなことより最初にやっておかないちゃいけないことがある、

"Hello, World," Lisp Style

プログラム解説書の掟"hello, world"

CL-USER> "hello, world"
"hello, world"

とするだけで、目的は達成できる。

"hello, world"は、ストリングでself-evaluatingオブジェクトなので、評価して"hello, world"が表示される。

もうちょっと普通のHello,Worldの例

format関数を使う。

CL-USER> (format t "hello, world")
hello, world
NIL

hello, worldと表示して、format関数の返り値である、NILが返っている。

NILは、Lispにおける真偽値の偽という意味。

もうちょっと進んで関数を作って表示させてみる。

関数の作成には、defunを使う。

CL-USER> (defun hello-world () (format t "hello, world"))
HELLO-WORLD

関数の名前で使える文字のうちでLisp的なところは、"-"が使えるところ。

hello_worldや、HelloWorldという名前より、hello-worldという名前が好まれる。

実行してみる。

CL-USER> (hello-world)
hello, world
NIL

hello, worldと表示してNILが返っている。

これは、関数の中で最後に評価された値が関数の返り値となるため。この場合はformat関数の返り値。

Saving Your Work

作った関数を保存するには->Emacsでファイルを.lispや、.clというファイルを作成してそれに書く。

SLIME: C-c C-q (slime-close-parens-at-point)

<<最新のCVS版SLIME(Lisp in a Boxではなく単体のもの)では代わりにslime-close-all-parens-in-sexpを使えとのこと。(slime-editing-commands.elの説明より)

SLIME: C-c C-] (slime-close-all-parens-in-sexp)

となっています。>>

SLIME:C-c C-c (slime-compile-defun)

エディタバッファのコンパイルしたい式の上で、C-c C-cを押すと式がコンパイルされる。

とりあえず、hello-world.lispという名前で関数の定義を保存。

一旦slimeを終了させて、再度、M-x slimeで起動。

(hello-world)を評価。

→エラー

ややこしい画面がREPLに表示される。これから抜けるには、"q"を押す。

hello-worldは定義されていないのでエラーになるのです。という訳で、保存したファイルを再度読み込ませる必要あり。

(load "hello-world.lisp")

で読み込ませる。

他の方法として、ファイルをコンパイルしてから、それを読み込ませるという方法もあり。

(load (compile-file "hello-world).lisp")

という感じになる。

上記2つの手順は、SLIMEでショートカットも定義されている

SLIME:C-c C-l (slime-load-file)
 指定したファイルをロード
SLIME:C-c C-k (slime-compile-and-load-file)
 指定したファイルをコンパイルしてからロード

まだまだ色々あるけど、この流れがLisp開発の基本。

REPLを使って新しいコードをロード、テスト、デバッグする。

本格的になると、終日同じ環境でプログラムを開発する人も結構いる。一旦立ち上げられた環境(イメージと呼ばれる)でプログラムは徐々に成長して行く。

REPL武勇伝:160万km彼方のNASAの宇宙探索機 Deep Space 1のバグを遠隔操作のREPLで対話的かつ動的に修正。

ゲスト



トラックバック - http://cadr.g.hatena.ne.jp/g000001/20071204