Next: , Previous: Mapping Functions, Up: Functions


11.7 無名関数

Lispでは、関数とは、lambdaで始まるリスト、 そのようなリストをコンパイルしたバイトコード関数、 あるいは、基本関数のsubrオブジェクトです。 名前は『余分』なのです。 普通の関数はdefunで定義し、そのとき名前を与えますが、 明示的なラムダ式、つまり、無名関数を使ったほうがより簡素な場合もあります。 そのようなリストは、関数名を使える場面ならば、どこでも使えます。

そのようなリストをどんな方法で作っても、正しい関数となります。 つぎのようにしてもかまわないのです。

     (setq silly (append '(lambda (x)) (list (list '+ (* 3 4) 'x))))
      (lambda (x) (+ 12 x))

これは、(lambda (x) (+ 12 x))のようなリストを計算し、 その値をsillyの値(関数定義ではない!)とします。

この関数はつぎのように呼び出せます。

     (funcall silly 1)
      13

(silly 1)と書いても動作しない。 なぜなら、この関数は、silly関数定義ではないからである。 sillyには関数定義を与えてなく、 変数としての値を与えただけである。)

ほとんどの場合、無名関数は読者のプログラムに現れる定数です。 たとえば、関数mapcarの引数の1つに渡したいときなどです。 mapcarは、リストの各要素に指定した関数を適用します。

第3引数に関数を取る関数change-propertyを定義します。

     (defun change-property (symbol prop function)
       (let ((value (get symbol prop)))
         (put symbol prop (funcall function value))))

ここで、数を2倍する関数を渡してchange-propertyを使う 関数を定義します。

     (defun double-property (symbol prop)
       (change-property symbol prop '(lambda (x) (* 2 x))))

このような場合、つぎのように、無名関数をクォートするには、 単純なクォートのかわりにスペシャルフォームfunctionを使います。

     (defun double-property (symbol prop)
       (change-property symbol prop
                        (function (lambda (x) (* 2 x)))))

quoteのかわりにfunctionを使った場合に違いがでるのは、 関数double-propertyをコンパイルしたときです。 たとえば、double-propertyの2番目の定義をコンパイルすると、 無名関数もコンパイルされます。 一方、普通のquoteを使った最初の定義をコンパイルすると、 change-propertyへ渡す引数は、書いたとおりのリストです。

     (lambda (x) (* x 2))

Lispコンパイラは、このリストが関数に見えたとしても、 このリストを関数とはみなしません。 というのは、コンパイラにはchange-propertyがリストになにを行うか わからないからです。 たぶん、第3要素のcarがシンボル*か どうか調べればよいのでしょう! functionを使うと、コンパイラに対して先へ進んで 定数の関数をコンパイルしても安全であることを伝えます。

関数名をクォートするときにquoteのかわりにfunctionを 書くこともありますが、この用法はコメントのようなものです。

     (function symbol) == (quote symbol) == 'symbol

入力構文#'は、functionの省略形です。 たとえば、

     #'(lambda (x) (* x x))

は、つぎと等価です。

     (function (lambda (x) (* x x)))
— Special Form: function function-object

このスペシャルフォームは、function-objectを評価せずに function-objectを返す。 この意味ではquoteに等価である。 しかし、これは、Emacs Lispコンパイラに対しては注意書きとして働き、 function-objectを関数としてのみ使う意図があり、 したがって、コンパイルしても安全であることを意味する。 Quotingquoteと比較してほしい。

functionと無名関数を用いた実際的な例は、 Accessing Documentationdocumentationを参照してください。