Next: , Previous: , Up: プログラム構造   [Contents][Index]


2.1 引数リスト

Emacs Lispの関数の引数リストの表記法はCommon Lisp表記法のサブセットで ある。よく知られた&optional&restマーカと同様に、Common Lispは付加引数に既定値を指定でき、追加のマーカ&key&aux を提供する。

引数の構文解析はEmacsに組み込まれているため、このパッケージがCommon Lispの引数リストをシームレスに実装する方法はない。その代わりに、この パッケージはCommon Lisp引数リストが必要なら 使わなければならないいくつかのLispフォームの代替を定義する。

Special Form: defun* name arglist body...

このフォームは、arglistが完全なCommon Lisp引数リストであることを 許されていることを除いて正規のdefunフォームと同一である。また、 関数本体はnameと呼ばれる暗黙のブロックに囲まれている; see ブロックと脱出

Special Form: defsubst* name arglist body...

これは定義される関数が自動的にinlineとグローバルに 宣言されることを除いて、ちょうどdefun*と似ている、 すなわちそれへの呼び出しはバイトコンパイラでインラインコードへ 展開されるかもしれない。これはEmacs 19のdefsubstフォームと 似ている; defsubst*はすべてのEmacsの版で動作し、幾分効率的な インライン展開を生成する別の方法(コンパイラマクロ)を使う。特に、 defsubst*は可能ならばいつでもコンパイル時にキーワード引数、 既定値、その他を処理できるように準備する。

Special Form: defmacro* name arglist body...

これは、arglistが完全な Common Lisp引数リストであることを 許されていることを除いて正規のdefmacroフォームと同一である。 &environmentキーワードはSteeleに記述されているように サポートされている。&wholeキーワードは分配リスト内のみで サポートされている(下記参照); トップレベルの&wholeは現在の Emacs Lispインタプリタでは実装できない。マクロエクスパンダ本体は nameと呼ばれる暗黙のブロックに囲まれている。

Special Form: function* symbol-or-lambda

これは、引数がlambdaフォームならそのフォームは完全なCommon Lisp 引数リストを使ってよいことを除いて正規のfunctionフォームと同一 である。

また、arglistをその文法に含むこのパッケージで定義された (defsetffletのような)すべてのフォームは完全なCommon Lisp引数リストを許す。

あなたの関数から多くのCL機能にアクセスするためにdefun*を 使う必要はないことに注意せよ。これらの機能は常に存在する; defun*defunの相違は単により柔軟な引数リストとその暗黙 のブロックである。

Common Lisp引数リストの完全なフォームは

(var...
 &optional (var initform svar)...
 &rest var
 &key ((keyword var) initform svar)...
 &aux (var initform)...)

5つの引数リスト節はそれぞれ付加的である。svarinitform、 そして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個の引数は通常の方法でabに束縛される。残りの 引数は:c:d、または:eに続いてその対応する 引数変数に束縛される値であるようなフォームの対でなければならない。 (その名前がコロンで始まるシンボルはキーワードと呼ばれ、 nilt同様に自己引用的である)

たとえば、呼び出し(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-keysfind-thingmember*が互いのキーワード引数に不平を 言わないようにするのに使われる。

(かなりの)性能最適化のために、このパッケージは“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 宣言)、不正な引数の 数や無効なキーワード引数のエラーチェックは無効である。既定では、引数 リストは厳しくチェックされる。


Next: , Previous: , Up: プログラム構造   [Contents][Index]