Common Lisp の変数と関数を定義する方法まとめ
Common Lispでの変数と関数の種類、定義についてのメモです。
変数を定義する
グローバル変数
グローバル変数のことをトップレベル定義と呼ぶ。defparameterまたはdefvarで定義する。defvarで定義した場合、値を上書きすることができない。
変数名をアスタリスクで挟む慣習がある。
defparameterで定義した場合:
CL-USER> (defparameter *foo* 5) *FOO* CL-USER> *foo* 5 CL-USER> (defparameter *foo* 3) *FOO* CL-USER> *foo* 3
defvarを定義した場合:
CL-USER> (defvar *bar* 5) *BAR* CL-USER> *bar* 5 CL-USER> (defvar *bar* 3) *BAR* CL-USER> *bar* 5
ローカル変数
ローカル変数は、それを定義した関数やブロックの内部でのみ使用できる変数。letコマンドで定義する。
(let (変数定義) 処理 )
変数定義は(変数名 初期値)のように行う。
例:
CL-USER> (let ((a 5) (b 6)) (+ a b)) 11
同じスコープで定義しているローカル変数を使った定義をしたいときは、let*を使う。
;; letだとエラー CL-USER> (let ((a 5) (b (+ a 2))) b) ; Evaluation aborted on #<SYSTEM::SIMPLE-UNBOUND-VARIABLE #x000000020033B8F9>. CL-USER> (let* ((a 5) (b (+ a 2))) b) 7
関数を定義する
グローバル関数
defunを使う。
(defun 関数名 (引数1 引数2 ... ) ; 処理 )
例:
CL-USER> (defun mean (a b) (ash (+ a b) -1)) MEAN CL-USER> (defparameter a 10) A CL-USER> (defparameter b 20) B CL-USER> (mean a b) 15
ローカル関数
ローカル関数は、それを定義した関数やブロックの内部でのみ有効になる。fletコマンドまたはlabelsコマンドで定義する。
(flet ((関数名 (引数) 関数の処理 )) 本体の処理)
例:
CL-USER> (flet ((f (n) (+ n 10)) (g (n) (- n 3))) (g (f 5))) 12
labelsコマンドを利用すると、ローカル関数定義の内部で、同じスコープで定義したローカル関数を使うことができる。ローカル関数が自分自身を呼び出すこともできるので、再帰関数を作るときにも使われる。
例:
CL-USER> (labels ((a (n) (+ n 5)) (b (n) (+ (a n) 6))) (b 10)) 21
まとめ
以下のコマンドを用いる。
グローバル変数:defparameter, defvar
ローカル変数 :let
グローバル関数:defun
ローカル関数 :flet, labels
labelsコマンドは再帰関数に利用される。
参考
コンラッド・バルスキ(2013)「Land of Lisp」 川合史郎訳 オライリー・ジャパン