6.1 ラムダ式

ラムダ式は関数を定義するためのリスト。
lambdaという記号で始まる。
;; 2乗を計算する関数を表すラムダ式
(lambda (x) (* x x))
xがこの関数のパラメータ。(* x x)が本体。

リストフォームがラムダ式で始まっていれば,
そのラムダ引きの定義する関数が呼び出される。
引数の取扱いは,関数名で始まる関数呼び出しと同じ。
> ((lambda (x) (* x x)) 3)
9

(defun square (x) (* x x))
(lambda (x) (* x x))
を表す関数にsquareという名前をつけただけ。
関数名をつけておけば,
> (square 3)
9
とかして,簡単に呼び出せる。

lambda

ラムダ式は記号lambdaに続いてパラメータの指定があり,
その後に本体を構成する式がくる。
(lambda ラムダリスト 式1...式n)
ラムダ式で定義される関数が呼び出されると,
本体の各式が順次評価されて,最後の式nの値を関数の値として返す。
''ラムダリスト: ラムダ式が定義する関数のパラメータを指定するリスト。''
defunで定義される関数も本質的にはラムダ式で定義されるので,
パラメータリストと呼んでいたものがラムダリストに対応する。
defunの一般形
(defun 関数名 ラムダリスト
  式1 ... 式n)

ラムダリストの一般形
(変数*
 [&optional オプショナルパラメータ指定*]
 [&rest 変数]
 [&key キーワードパラメータ指定*
       [&allow-other-keys]]
 [&aux 補助変数指定*])
意味
[A] Aがあってもなくても良い
A* Aのいくつかの並び(1つもない場合を含む)

&...はラムダリストキーワードと呼ばれる。
ラムダリストキーワードよりも前に現れる変数は必須パラメータとよばれ,
関数が呼び出された時に必ずそれらに対応する引数が無ければならない。

&optional

オプショナルパラメータを指定する。
関数呼び出しのときに対応する引数があってもなくてもいい。
((lambda (x y &opeitonal ...) ...)
  1 2 3 4 ...)
では,引数1と2が必須パラメータxとyに対応する。
3が最初のオプショナルパラメータ,4が次のオプショナルパラメータというふうに対応する。
オプショナルパラメータは,対応する引数があればその引数を初期値とし,
そうでなければ,ラムダリストに指定された値(デフォルト値)を初期値とする。

オプショナルパラメータは,一般に3つの要素からなるリストで指定する。
(変数 式 判定変数)
変数 オプショナルパラメータとして使う局所変数の名前
デフォルト値を与える式
判定変数 対応する引数があったかどうかを判定するために使われる局所変数の名前。対応する引数があれば判定変数はtにバインドされ,なければnilにバインドされる。

オプショナルパラメータの式,判定変数は省略できる。
(変数 式)
(変数)
あるいはリストでなく
変数
でもよい。


> ((lambda (a &optional (b 3 c))
     (list a b c))
    1 2)
(1 2 T)
a 必須パラメータ
b オプショナルパラメータ
c bの判定変数
bに引数2が与えられているため,bは2にバインド。
式3は評価されず,判定変数cはtとなる。

> ((lambda (a &optional (b 3 c))
     (list a b c))
    1)
(1 3 nil)
bに引数が与えられていないため,bは式3を評価した値(3)にバインド。
判定変数cはnilとなる。

&rest

restパラメータ。残余パラメータ。
関数への引数のうち,必須パラメータとオプショナルパラメータに対応するもの以外からなるリストがバインドされる。
CL-USER> ((lambda (a &optional b &rest c)
	    (list a b c))
	  1 2 3 4)
(1 2 (3 4))

CL-USER> ((lambda (a &optional b &rest c)
    (list a b c))
  1 2)
(1 2 NIL)

CL-USER> ((lambda (a &optional b &rest c)
    (list a b c))
  1)
(1 NIL NIL)

&key

キーワードパラメータの指定
CL-USER> (defun cons* (&key ((:car x) 1)
 		             ((:cdr y) 2))
	   (cons x y))
CONS*
((:car x) 1)と((:cdr y) 2)がキーワードパラメータの指定。
変数xとyがキーワードパラメータ。
1と2がキーワードパラメータのデフォルト値。
:carと:cdrはコロンで始まっているので,キーワードパッケージの記号(キーワード)である。

cons*の引数にキーワード:carがあればその次の引数がxの初期値となり,
:cdrがあればその次に引数がyの初期値になる。
CL-USER> (cons* :cdr 4)
(1 . 4)
:cdrの値は:cdrである。
CL-USER> (cons* :car 3 :cdr 4)
(3 . 4)
CL-USER> (cons*)
(1 . 2)

個々のキーワードパラメータの指定は一般に次の形のリスト。
((キーワード 変数) 式 判定変数)
式と判定変数は,指定しなければnilが使われる。
(x 式)
((:x x) 式)
と同じ。

(x)
は,
((:x x))
x
と書いても良い。
cons*をこう書いてもいい。
CL-USER> (defun cons* (&key (x 1)
	             (y 2))
    (cons x y))

allow-other-keys

ラムダリストで指定された以外のキーワードを使うと通常はエラー。
引数リストの中に:allow-other-keysというキーワードがあり,
その次の引数がnil以外ならエラーにならない。
CL-USER> (cons* :allow-other-keys t :vehicle 3 :cdr 4)
(1 . 2)
または,ラムダリストキーワードに &allow-other-keys を書いておく。
CL-USER> (defun cons* (&key (x 1) (y 2)
	        &allow-other-keys)
    (cons x y))
CONS*
CL-USER> (cons* :vehicle 3 :cdr 4)
(1 . 2)

&aux

補助変数(auxiliary variable)とは,関数内で局所的に使用する変数。
局所変数は,letやlet*でも宣言できるが,&auxを使うと関数定義がコンパクトになる。
(lambda (a b) (let* ((c 1) (d 2)) ...))
(lambda (a b &aux (c 1) (d 2)) ...)
とかける。
最終更新:2011年10月07日 14:43