Emacs Lispの関数の引数リストの表記法はCommon Lisp表記法のサブセットで
ある。よく知られた&optional
と&rest
マーカと同様に、Common
Lispは付加引数に既定値を指定でき、追加のマーカ&key
と&aux
を提供する。
引数の構文解析はEmacsに組み込まれているため、このパッケージがCommon Lispの引数リストをシームレスに実装する方法はない。その代わりに、この パッケージはCommon Lisp引数リストが必要なら 使わなければならないいくつかのLispフォームの代替を定義する。
このフォームは、arglistが完全なCommon Lisp引数リストであることを
許されていることを除いて正規のdefun
フォームと同一である。また、
関数本体はnameと呼ばれる暗黙のブロックに囲まれている;
see ブロックと脱出
これは定義される関数が自動的にinline
とグローバルに
宣言されることを除いて、ちょうどdefun*
と似ている、
すなわちそれへの呼び出しはバイトコンパイラでインラインコードへ
展開されるかもしれない。これはEmacs 19のdefsubst
フォームと
似ている; defsubst*
はすべてのEmacsの版で動作し、幾分効率的な
インライン展開を生成する別の方法(コンパイラマクロ)を使う。特に、
defsubst*
は可能ならばいつでもコンパイル時にキーワード引数、
既定値、その他を処理できるように準備する。
これは、arglistが完全な Common Lisp引数リストであることを
許されていることを除いて正規のdefmacro
フォームと同一である。
&environment
キーワードはSteeleに記述されているように
サポートされている。&whole
キーワードは分配リスト内のみで
サポートされている(下記参照); トップレベルの&whole
は現在の
Emacs Lispインタプリタでは実装できない。マクロエクスパンダ本体は
nameと呼ばれる暗黙のブロックに囲まれている。
これは、引数がlambda
フォームならそのフォームは完全なCommon Lisp
引数リストを使ってよいことを除いて正規のfunction
フォームと同一
である。
また、arglistをその文法に含むこのパッケージで定義された
(defsetf
やflet
のような)すべてのフォームは完全なCommon
Lisp引数リストを許す。
あなたの関数から多くのCL機能にアクセスするためにdefun*
を
使う必要はないことに注意せよ。これらの機能は常に存在する;
defun*
とdefun
の相違は単により柔軟な引数リストとその暗黙
のブロックである。
Common Lisp引数リストの完全なフォームは
(var... &optional (var initform svar)... &rest var &key ((keyword var) initform svar)... &aux (var initform)...)
5つの引数リスト節はそれぞれ付加的である。svar、initform、 そしてkeyword部分は付加的である; 省略するなら、 ‘(var)’は単に‘var’と書いてもよい。
第1節は0個かそれ以上の必須引数から成る。これらの引数は関数 呼び出し時には常に指定しなければならない; 必須引数に関する限り、Emacs LispとCommon Lispに相違はない。
第2節は付加引数から成る。これらの引数は関数呼び出し時に
指定してもよい; 指定されない場合、initformは引数として使われる
既定値を指定する。(initformがない場合は既定値としてnil
を
使うことを意味する) initformは先立つ引数がすでに確立した
束縛とともに評価される; (a &optional (b (1+ a)))
は1個または
2個の引数とマッチし、2番目の引数は1番目の引数に1を加えた値を
既定値とする。svarが指定されると、付加引数が指定された場合は
t
に、引数が省略された場合はnil
に束縛される
補助変数になる。svarを使わない場合、引数なしで呼び出されたのか、
引数として既定値を明示的に渡されたのかを知る方法はない。
第3節は1個のrest引数から成る。必須引数と付加引数が占めるより
多くの引数が関数へ渡された場合、それらの余分な引数は1個のリストに
集積され“rest”引数変数に束縛される。Common Lispの&rest
は
Emacs Lispのそれと同等である。Common Lispはマクロコンテキストで
&rest
の同義語として&body
を受け入れる;
このパッケージはいつでもそれを受け入れる。
第4節はキーワード引数から成る。これらは引数リスト中の 位置ではなく名前で指定される付加引数である。たとえば、
(defun* foo (a &optional b &key c d (e 17)))
は1個、2個、またはそれ以上の引数で呼び出してもよい関数を定義する。
最初の2個の引数は通常の方法でa
とb
に束縛される。残りの
引数は:c
、:d
、または:e
に続いてその対応する
引数変数に束縛される値であるようなフォームの対でなければならない。
(その名前がコロンで始まるシンボルはキーワードと呼ばれ、
nil
やt
同様に自己引用的である)
たとえば、呼び出し(foo 1 2 :d 3 :c 4)
は5個の引数をそれぞれ1、
2、4、3、そして17にセットする。同じキーワードが1度以上関数呼び出しに
現れる場合、第1の出現が後の出現より優先する。付加引数b
を
指定することなくキーワード引数を指定することはできないことに注意せよ、
なぜなら(foo 1 :c 2)
はb
をキーワード:c
に束縛し、
2
は有効なキーワードではないためエラーを通知するからである。
keywordシンボルが上のように引数リストに明示的に指定される場合、 そのキーワードは1個のコロンを接頭辞とする単なる変数名の代わりに 使われる。まったくコロンで始まらないkeywordシンボルを 指定できるが、そのようなシンボルは自己引用的ではない; 関数呼び出し中で 明示的にアポストロフィで引用しなければいけない。
通常、たとえば(foo 1 2 :c 3 :goober 4)
のように、
認められていないキーワードを関数に渡すことはエラーである。引数リストの
キーワード節の後にマーカ&allow-other-keys
を加えるか、呼び出し
時にnil
ではない値の:allow-other-keys
引数を
指定することで、認められていないキーワードを無視するようLispに
求めることができる。関数が&rest
と&key
を同時に
両方使うと、“rest”引数は呼び出し時に現れるキーワードリストに
束縛される。たとえば:
(defun* find-thing (thing &rest rest &key need &allow-other-keys) (or (apply 'member* thing thing-list :allow-other-keys t rest) (if need (error "Thing not found"))))
この関数はキーワード引数:need
をとるが、関数member*
へ
渡される他のキーワード引数も受け入れる。allow-other-keys
は
find-thing
とmember*
が互いのキーワード引数に不平を
言わないようにするのに使われる。
(かなりの)性能最適化のために、このパッケージは“rest”引数中の
キーワード検索にmemq
を呼び出すことでキーワード引数の走査を
実装する。技術的には、memq
は奇数個の値を偶数個のキーワードと
同様に見るのでこれは正しくない。キーワードシンボルが同じ関数の有効な
キーワード引数の名前と偶然同じ場合、キーワードシンボルを別のキーワード
引数の値として偶然渡すと、キーワード構文解析部は
混乱することになる。このあまり重要でないバグは、プログラム中で
キーワードシンボルを一般用途のデータとして使うときにのみ影響がある
場合がある; この習慣はEmacs Lispでは強く反対される。
引数リストの第5節は補助変数から成る。これらは実際にはまったく
引数ではなく、関数実行時nil
または指定されたinitformsに
束縛される単なる変数である。スタイル上の好みの問題を除いて、下記の
2個の関数間に相違はない:
(defun* foo (a b &aux (c (+ a b)) d) body) (defun* foo (a b) (let ((c (+ a b)) d) body))
引数リストは分配をサポートする。Common Lispでは、分配は
defmacro
でのみ許される;このパッケージはdefun*
や他の引数
リストでも同様に許す。分配では、全引数変数(上のvar)は変数の
リストか、より一般的には再帰引数リストで置き換えることができる。
対応する引数値は、その要素が再帰引数リストにマッチする
リストでなければならない。たとえば:
(defmacro* dolist ((var listform &optional resultform) &rest body) ...)
これは、dolist
の第1引数は2個または3個の項目の
リストでなければならないことを示す。このリスト同様に他の引数があれば、
body
に格納される。正規の引数リストで許されるすべての
機能はこれらの再帰引数リストで許される。さらに、
‘&whole var’節は再帰引数リストの先頭で許される。それは
varをマッチしたリスト全体に束縛する; したがって、
(&whole all a b)
は2つのもののリストにマッチし、a
は
1番目のものに束縛され、b
は2番目のものに束縛され、all
はそのリスト自身に束縛される。(Common Lispはトップレベルの
defmacro
引数リストでも同様に&whole
を許すが、Emacs Lisp
はこの使用法をサポートしない)
分配の最後の機能は、引数リストはドットでもよいということである、だから
引数リスト(a b . c)
は機能的には(a b &rest c)
と同等である。
最適化品質safety
に0が設定されると(see 宣言)、不正な引数の
数や無効なキーワード引数のエラーチェックは無効である。既定では、引数
リストは厳しくチェックされる。