プログラミング原人の進化ログ

プログラミング原人の進化論

オレ プログラミング ベンキョウ スル。マナンダ コト カク。

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」 川合史郎訳 オライリー・ジャパン