次: Function Cells, 前: Mapping Functions, 上: Functions
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)))
このスペシャルフォームは、function-objectを評価せずに function-objectを返す。 この意味では
quoteに等価である。 しかし、これは、Emacs Lispコンパイラに対しては注意書きとして働き、 function-objectを関数としてのみ使う意図があり、 したがって、コンパイルしても安全であることを意味する。 Quotingのquoteと比較してほしい。
functionと無名関数を用いた実際的な例は、
Accessing Documentationのdocumentationを参照してください。