Lisp(LISt Processor)は仕様が小さいために、さまざまな方言が生まれてしまった。
そこで、これらの方言を統一しようという事で生まれたのがCommon Lispだ。
ANSIで標準化されていることにも注意していただきたい。これは、実装があって仕様が付いてくる言語(Python,Ruby,VB......etc)とは違い、仕様があるのに合わせてさまざまな処理系が作られている。
このように、仕様が先にあって実装が後に来るということは今日書いたコードが10年後もそのまま動く可能性が高いということである。
これはC/C++やCommon Lispにしか見られない特徴なんじゃないかな?
実用という点では、Schemeはあまり適しているとはいえない。 また、両者には学習段階でも変数の扱いや関数名の差異が見られる。両方やって好きな方をやるよろし。
まず、処理系を選ばなくてはならない。 代表的なものとして、
名前 | 詳細 | ライセンス |
sbcl | ネイティブコードコンパイラで、使っている人も一番多いと思われる。フリーの処理系では最速。 | 修正BSD/パブリックドメイン |
Clisp | バイトコードコンパイラ。sbclの次くらいに人気 | GNU GPL |
が、お手軽だ。学習用ならどちらも大差は無い。*1
apt-get install sbcl apt-get install clisp
のどちらかを実行すれば、インストールできるはず。
ただし、Debianのパッケージは結構古いので
特にsbclに関しては、公式サイトから最新版を落としてインストールすることを勧めたい。
上を参考にどうぞ
Clispとsbclでググれば公式サイトが出てくるからそこでダウンロードすればいい。
インストールはほぼ自動だから楽チン。
コマンドプロンプト等でsbclかclispと入力したら起動するはず *2
[1]>
とか
*
とか出ていれば成功だ。
この状態は、対話式の入出力環境でREPL(Read-Eval-Print-loop)と呼ばれる。
早速、REPLに入力してみよう。
;よりあとはコメントを表すので入力しなくてよい。(ここでは出力をメモしておいただけ)
(format t "Hello world") ; Hello world
format関数は出力をするのに非常に強力で便利な関数なのだ。
(+ 98 1) ; >> 99
演算子が頭にある。これこそがLispの特徴だ。
ここではとりあえず関数は() ......すなわちリストの頭に表記して引数をその後に入力するという事を覚えてもらいたい。
尚、次のような表記も有効だ。
( + 3 8 ) ; >> 11
このように、スペースが二つ以上になると無視される。
引き算は次のようにする。
(- 30 14) ; >> 16 (- 3 6) ; >> -3
(* 5 7) ; >> 35 (/ 3 2) ; >> 3 / 2 (/ 3.0 2) ; >> 1.5 (mod 3 2) ; >> 1 (mod 10 4) ; >> 2 (/ 1 0) ; -----エラーが表示される。
掛け算は他のプログラミング言語と大差ないだろう。(演算子の前置記法以外は)
問題は割り算だ。2番目の例を見れば分かると思うが、Common Lispでは分数を使う事ができる。
ただし、小数を割る時には成り立たない。
また、モデュラー算術も可能だ。
このほかにも、さまざまな算術のための機能が実装されている。
関数の定義には、defun関数を使用する。
構文は、
(defun 関数名 (引数1 引数2 ......) 実行してほしい処理)
だ。さっそく例を見てみよう。
>>(defun 3jo (x) (* x x x)) 3jo >>(3jo 2) 8
>>(defun 3jo (x) (* x x x) () ) 3jo >>(3jo 8) nil
二つの例を見比べてみると、実行してほしい処理のところが
(* x x x) と (* x x x) () との2通りがある。
実は、defunで作られた関数は最後に実行した処理によって出てきた値を返り値として返すのだ。
これは実は関数プログラミングの根幹を成すものである。
Common Lispでは、Return文は必ずしも必要ではないのだ。
ところでこの nil というのはなんだろうか。
これは否定の論理演算子だ。(nihilのことじゃないかな)
nilとt (trueのこと)は変数として使用する事が出来ない。
(defparameter *oppai* 99)
とすると、グローバル変数が定義できる。
今回は、*oppai*という変数に99を代入している。
*oppai*
とREPLで入力すれば、99が返ってくる。
この変数の周りの *(アスタリスク)はグローバル変数であることを強調するための、Common Lispにおけるマナーのようなものだ。*3
他にグローバル変数と定義する方法として、
(defvar *foo* 10)
とする方法がある。
(defvar *foo* 10) (defvar *foo* 8)
としても、*foo*の値は10のままであるから注意が必要だ。
(setf((setqというのもあるが、setfの方が新しい。また、setfの使用が推奨されている。)) *foo* 8)
とすれば、値を変更できる。
(defconstant お名前 値)
でできる。 setfで値を変更する事は出来ない。