Go to the first, previous, next, last section, table of contents.

ラムダ式

(これまでに) Lisp でプログラムを組んだことのない人も大勢いらっしゃることでしょ う。 (関数を操作する機能の詳細に入る前に) "関数とは何であるか" を見直しておく ことが役立ちます。 Lisp プログラマはこのセクションは流し読みしてかまいません が、GNU Emacs Lisp 言語に固有な部分も何箇所か存在します。

Lisp 関数は、次のようなリストです。

      (lambda args documentation body)

(このような Lisp 式は、主に歴史的な理由でラムダ式として知られています)

リストの最初の要素はシンボル lambda で、2 番目の要素はアーギュメントのリスト で、3 番目の要素はこの関数のドキュメンテーションであるオプショナルなストリング で、その他の要素は実行を行なう Lisp のコードで Lisp プログラマが "評価する Lisp フォームのリスト" と呼ぶものです。この関数の返す値は、(この)本体の最後の 要素が返すものになります。

ラムダリストと呼ばれるアーギュメントのリストは、変数名のリストです。 Lisp 関数 が呼ばれると、アーギュメントはラムダリスト中の名前とマッチされ、(その)変数は与 えられた値にバインドされます。

関数が次のようなものであり、

      (lambda (a b d) "Test" (+ a b c))

それが次のように呼ばれると、

      (foo 1 2 3)

foo は、1 にバインドされた変数 a、 2 にバインドされた変数 b、 3 にバインドされ た変数 c、を持って評価されます。アーギュメントは(別の)関数の結果であってもかま わない点に注意して下さい。i.e.

      (foo 1 (* 2 3) (- 5 4))

foo に対するアーギュメント (1 と (* 2 3) と (- 5 4)) は左から右に評価されま す。その後 foo がこれらのアーギュメントに対し適用されます。

関数は(しばしば)それを名付けるシンボルに対応付けられます。例えば、foo はシンボ ルですが、 (通常) "そのシンボルの関数セルがポイントする関数" の意味で、関数 foo と参照します。

前の例の関数呼び出しでは、関数 foo に対しアーギュメントを 3つ与えなくてはいけ ませんでした。 foo を 2つのアーギュメント(だけ)で呼ぶとエラーになります。しか し rmail 関数では、(特定のファイル名が与えられない場合) あらかじめ定義された ファイル名をデフォルトとして用いるよう、あるアーギュメントに対し (ある方法で) デフォルトの値を指定することができると便利であることがあります。 (また)個数が いくつと決まっていないアーギュメントを与えることができると便利です。 and, or, + といった関数は、そのようなもののカテゴリに入ります。

関数を呼ぶ時に(与えても与えなくてもよい)オプショナルなアーギュメントを、指定す るためには、キーワード &optional をその(オプショナルな)アーギュメントの前に置 きます。 0 個以上のアーギュメントを指示するためには、最後の (1つの)アーギュメ ントの前にキーワード &rest を置きます。

ラムダ式の完全なシンタックスは、

      (lambda (required-vars* [&optional optional-vars*] [&rest rest-var])
         [documentation-string]
         [interactive-declaration]
         forms*)

&optional clause と &rest clause とそれに対する変数はオプショナルです。関数呼 び出しは、 required-vars の各々に対し actual アーギュメントを 1つずつ必要とし ます。 (0 個以上の) optional-vars に対し actual アーギュメントが存在していても かまいませんが、 (&rest が存在しない限り)それ以上 actual アーギュメントが存在 していてはいけません。 &rest が存在する場合、いくつ actual アーギュメントが追 加されていてもかまいません。 optional 変数及び rest 変数に対し actual アーギュ メントが与えられていない場合、それらは(常に) デフォルトで nil になります。

----------------

CN: これはオプショナルなパラメタに対し、デフォルトの値を与えうる Common Lisp の場合とは異なります。

----------------

例えば、次のようなラムダリストは

      (a b &optional c d &rest e)

a と b を(最初の) 2つの actual アーギュメントにバインドし、これは必要とされま す。 1 つもしくは 2 つのアーギュメントが(これ以外に)存在する場合、 c と d が 各々それにバインドされます。この他にアーギュメントが存在する場合、それらは(1つ の) リストに集められ、そのリストに e がバインドされます。呼び出し側で与えられ たアーギュメントが用いられてしまうと、 (残された) optional 変数や rest 変数は nil にバインドされます。

&optional の後の変数は(全て) オプショナルなアーギュメント用のものであり、&rest の後の変数は 1つだけ有効になります。なぜかと言うと、(例えば) c がオプショナル で d が必要とされるものであるとしてみましょう。 3 つの actual アーギュメントが 与えられた場合、 3 番目のアーギュメントには何がバインドされるべきでしょうか? (同様に) &rest 変数を複数持つことも意味がありません。

ここで小さな問題が 1つあります。 (それは)最後のアーギュメントが nil の場合で、 それがオプショナルなアーギュメントである場合、関数はアーギュメントが与えれれた か否かを判定することができません。

ラムダ式のシンタックスに戻ると、 documentation-string は言語に関する限り(完全 に)オプショナルです。与えれれた場合、これはユーザー用のいくつかの関数で用いら れるリテラルストリングになります。コマンドと関数(の全て)にドキュメンテーション ストリングを与えるのは良い考えで、それはその関数が何をするものであるかというこ とと、その(全ての)アーギュメントを順に説明するものであるべきです。

(その後に)関数で必要とされる要素(本体)が来るため、ドキュメンテーションストリン グがオプショナルであることを疑問に思われるかもしれませんが、ストリングの評価は 副作用を持たずそのストリングを返すため、本体の最後のフォームでなくても影響はあ りません。このため(実際に)本体の最初のフォームとドキュメンテーションストリング とを誤まることはありません。本体が 1つのストリングしか持たない場合、それはリ ターン値とドキュメンテーションの両方で用いられます。

interactive-declaration が存在する場合、これは (interactive code-string) とい うフォームで、その関数をインタラクティブに用いることができることを宣言します。 この宣言を持つ関数はコマンド(チャプター 17 [コマンド]、ページ 137 参照) と呼ば れます。

関数定義の残りの部分は、順に評価される Lisp フォームのリストであるだけで、その 最後のフォームの値が、その関数呼び出しの結果として返されます。

ラムダの使用例

      ((lambda (n) (1+ n))               ;1 パラメタ、
       1)                                       ;ちょうど 1つのアーギュメントを必要とする。
      => 2
      ((lambda (n &optional n1)         ;1 パラメタ と 1 オプショナル
               (if n1 (+ n n1) (1+ n))) ;1 つもしくは 2 つのアーギュメント
      1 2)
      => 3
      ((lambda (n &rest ns)             ;1 パラメタ と &rest
               (+ n (apply '+ ns)))     ;1 つもしくはそれ以上のアーギュメント
       1 2 3 4 5)
      => 15

Go to the first, previous, next, last section, table of contents.