Next: , Previous: , Up: Lambda Expressions   [Contents][Index]


13.2.3 引数リストのその他機能

シンプルなサンプル関数(lambda (a b c) (+ a b c))は3つの引数変数を指定しているので、3つの引数で呼び出されなければなりません。引数を2つしか指定しなかったり4つ指定した場合にはwrong-number-of-argumentsエラーとなります(Errorsを参照)。

特定の引数を省略できる関数を記述できると便利なこともあります。たとえば関数substringは3つの引数 — 文字列、開始インデックス、終了インデックス — を受け取りますが、3つ目の引数を省略すると、デフォルトでその文字列のlengthとなります。関数list+が行うように、特定の関数にたいして不定個の引数を指定できると便利なときもあります。

関数が呼び出されるとき省略されるかもしれないオプションの引数を指定するには、オプションの引数の前にキーワード&optionalを含めるだけです。0個以上の追加引数のリストを指定するには、最後の引数の前にキーワード&restを含めます。

したがって引数リストの完全な構文は以下のようになります:

(required-vars[&optional optional-vars]
 [&rest rest-var])

角カッコ(square bracket)は&optional&rest、およびそれらに続く変数が省略できることを示します。

この関数の呼び出しではrequired-varsのそれぞれにたいして、実際の引数が要求されます。0個以上のoptional-varsにたいして実際の引数があるかもしれませんが、ラムダ式が&restを使用していなければ、その個数を超えて実際の引数を記述することはできません。&restが記述されていれば、追加で任意の個数の実際の引数があるかもしれません。

optionaやrest変数にたいして実際の引数が省略されると、それらのデフォルトは常にnilになります。関数にたいして引数に明示的にnilが使用されたのか、引数が省略されたのかを区別することはできません。しかし関数のbodyが、nilを他の有意な値が省略されたと判断することは自由です。substringはこれを行います。substringの3つ目の引数がnilなら、それは文字列の長さを使用することを意味します。

Common Lispに関する注意: Common Lispではオプションの引数が省略されたときに使用するデフォルト値を指定できる。Emacs Lispでは、引数が明示的に渡されたかを調べるsupplied-p変数はサポートされない。

例えば引数リストは以下のようになります:

(a b &optional c d &rest e)

これはabは最初の2つの実引数となり、これらは必須です。さらに1つまたは2つの引数が指定された場合には、それらは順番にcdにバインドされます。1つ目から4つ目の引数の後の引数はリストにまとめられて、eにそのリストがバインドされます。したがって2つしか引数が指定されなかった場合にはcdenilになります。2つまたは3つの引数の場合にはdenilです。引数が4つ以下の場合には、enilになります。正確に5つの引数に明示的にnilが指定された場合には、eにたいして他の単一値が与えられたときのように、引数のnilが1要素のリスト(nil)としてeに与えられます。

オプションの引数の後ろに必須の引数を指定する方法はありません — これは意味を成さないからです。なぜそうなるかは、この例でcがオプションでdが必須な場合を考えてみてください。実際に3つの引数が与えられたとします。3番めの引数は何を指定したのでしょうか? この引数はcなのでしょうか、それともdに使用されるのでしょうか? 両方の場合が考えられます。同様に&rest引数の後に、さらに引数(必須またはオプション)をもつことも意味を成しません。

以下に引数リストと、それを正しく呼び出す例をいくつか示します:

(funcall (lambda (n) (1+ n))        ; 1つの必須:
         1)                         ; これは正確に1つの引数を要求する
     ⇒ 2
(funcall (lambda (n &optional n1)   ; 1つは必須で、1つはオプション:
           (if n1 (+ n n1) (1+ n))) ; 1つまたは2つの引数
         1 2)
     ⇒ 3
(funcall (lambda (n &rest ns)       ; 1つは必須で、後は残り:
           (+ n (apply '+ ns)))     ; 1つ以上の引数
         1 2 3 4 5)
     ⇒ 15