コマンドインタープリタとしてのgcl

★以下では,WordPressによってダブルクォートは全角文字“と”に自動変換されているのでコピペをする時は,半角にもどしてください.
コマンドインタープリタとしてのgclはコンソールから入力を受け取り(read),対応する処理を行い(eval(uation)),表示をする(print)というループをひたすら繰り返す.終了は,(bye).無限ループに入ってしまったら,入力は受け付けられなくなるが,そのときは,^c(コントロールcで強制終了).
1. お決まりのHello World表示なら,(print “Hello World!”)だけ.ただし,ほとんど感動はないが…

上で,(print “Hello World!”)はユーザの出力(最後に,Enterキーの押し下げをお忘れなく).その下に”Hello World!”が2行表示されている.第1行目は(print “Hello World!”)というコマンドの実行結果(正確には,副作用)としての”Hello World!”の表示(ダブルクォートも出力されている点に注意.煩わしいと思う向きには消す方法もある).第2行目は,コマンドを「計算」した結果,その「値」が”Hello World!”という文字列であることを表している.
たかがHello World.されどHello World.
副作用を伴わないコマンドの場合は,表示は1行になる.例えば,
(+ 1 2 3 4)
というコマンド(これは1+2+3+4という電卓みたいなコマンド)を続けて入力すると,今度は表示という副作用は生じないのでその結果の10が表示されるだけ.

自分でコマンドを定義することもできる.よく使われる例として,n!(「nの階乗」)を計算するfactorialを定義して10の階乗を計算してみよう.これまで示唆してきたようにLispのコマンドの基本形は(command名 空白 引数1 … 最後の引数)という格好をしている.(+ 1 2 3 (* 4 5))というようにコマンドの埋め込みも任意にできる.関数の定義をするコマンドはdefun.定義の仕方は少々複雑なので後回しにすることとして,「n!というのは,1!=1,それより大きなnについては,n × (n-1)!で計算する」といった趣旨のことを与える.すると,factorialを普通の組み込みコマンドと全く同様に使うことができる.

上から示唆されるように,Lispはもともと数学の定理証明などにも使われたので,big numberはお手のもの.
traceというコマンド(この呼び方は正確ではないが,現段階ではこれくらいでいいだろう)を使うと,factorialの計算過程を追跡できる.

実は,上のfactorialの定義は,プログラムとしてはあまり立派なものではない.引数として負の数を入力すると,止まらなくなるからだ.実際は処理系ではスタックオーバーフローというエラーになる.

プロンプトが>から>>に変わっている.これはbreak loopというものであり,後で述べるようにはデバッグには大変便利.break loopは何重にでもネストされる.:qは「トップレベル」に戻りなさいというコマンド.これでエラーの起きた「コンテキスト」から,まっさらのトップレベル「コンテキスト」にもどった.
先にも述べたように,実行系を終了すると,折角与えた定義は消えてしまう.これでは困るので,普通のプログラミングでは,定義式をファイルにあらかじめ与えておいて,読み込むという手順が踏まれる.このとき,Common Lisp特有の面白い性質は,エラーが生じない限り,定義式を与えたファイルを読ませることはコンソールの入力を(コマンド実行結果に関わらず)与えることと全く同じであることだ.
たとえば,My documents/gcl/の下に,sample1.lspというテキストファイルを作成し,そのなかに先に与えた(defun factorial …)を書いておいて,gclから,それを読み込めばよい.

上でデフォールトパス名として, “/Users/Nishida/Documents/gcl”を与えて,いちいちこの部分を繰り返さなくてもよいようにするためには
→変数*default-pathname-defaults*に当該ファイルのあるディレクトリパスをセットしておく.例えば,
(setq *default-pathname-defaults* “C:/Users/Nishida/Documents/gcl/”)
をgcl立ち上げ時に実行しておくと,(load “sample1”)によって, C:/Users/Nishida/Documents/gcl/sample1.lspにあるlisp式がread-eval-printによって実行される(.lspは省略可能).sample1.lspにはlispインタープリタが実行できる式であれば何を書いても構わない.通常は,(defun factorial …)といった定義式を書いておいて,定義式が実行され,定義が行われるようにする.
こうなると,プログラム開発と実行は,

  1. 一つまたは複数のファイルのなかに「コマンド」の定義を与える.
  2. それをgclに読み込んで,適当な引数を与えて実行する.

を繰り返すことになる.2でバグが見つかれば,インタープリタを使ってバグの原因を究明し,1に戻りプログラムを修正し,また,2に行けばよい.定義は重ね書きされるから,インタープリタは動かしたままでよい.

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です