関数は通常はdefun
により定義されて、同時に名前が与えられますが、明示的にラムダ式を使う — 無名関数(anonymous
function)のほうが便利なときもあります。無名関数は名前つき関数が有効な場所ならどこでも有効です。無名関数は変数や関数の引数に割り当てられることがよくあります。たとえばある関数をリストの各要素に適用するmapcar
のfunction引数に渡すかもしれません(関数のマッピングを参照)。現実的な例はdescribe-symbols exampleを参照してください。
無名関数として使用するためのラムダ式を定義するとき通常はマクロlambda
、スペシャルフォームfunction
、または入力構文#'
を使用するべきです。
このマクロは引数リストargs、(もしあれば)ドキュメント文字列doc、(もしあれば)インタラクティブ指定interactive、およびbodyで与えられるbodyフォームをもつ無名関数をリターンする。
たとえばこのマクロはlambda
フォームをほとんど自己クォートする。CARがlambda
であるようなフォームはほとんどフォーム自身のような値を得る:
(lambda (x) (* x x)) ⇒ #f(lambda (x) :dynbind (* x x))
レキシカルバインディングの下で評価した際には、結果は:dynbind
マーカーをキャプチャーした変数に置き換えた、クロージャに似たオブジェクトになることに注意(クロージャーを参照)。
lambda
フォームは別の1つの効果をもつ。このマクロはfunction
(以下参照)をサブルーチンとして使用することにより、Emacs評価機能(Emacs
evaluator)とバイトコンパイラーに、その引数が関数であることを告げる。
このスペシャルフォームは評価を行わずにfunction-objectの関数値をリターンする。多くの点においてquote
(クォートを参照)と似ている。しかしquote
とは異なり、Emacs評価機能とバイトコンパイラーに、これを関数として使用する意図を告げる役割をもつ。function-objectが有効なラムダ式と仮定すると、これは2つの効果をもつ:
function-objectがシンボルかつバイトコンパイル済みコードの場合には、その関数が未定義、あるいは実行時に認識されていなければバイトコンパイラーは警告を発する。
入力構文#'
はfunction
の使用の略記です。以下のフォームは等価です:
(lambda (x) (* x x)) (function (lambda (x) (* x x))) #'(lambda (x) (* x x))
以下の例では3つ目の引数に関数をとるchange-property
関数を定義して、その後のchange-property
で無名関数を渡してこれを使用しています:
(defun change-property (symbol prop function) (let ((value (get symbol prop))) (put symbol prop (funcall function value))))
(defun double-property (symbol prop) (change-property symbol prop (lambda (x) (* 2 x))))
lambda
フォームをクォートしていないことに注意してください。
上記のコードをコンパイルすると無名関数もコンパイルされます。リストをクォートすることにより無名関数を構築した場合にはコンパイルはされません。
(defun double-property (symbol prop) (change-property symbol prop '(lambda (x) (* 2 x))))
この場合、無名関数はコンパイルされたコード内のラムダ式に保持されます。バイトコンパイラーはchange-property
が関数としての使用を意図していることを知ることができないので、たとえこの関数が関数のように見えるとしても、このリストが関数であると決め込むことができません。