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
を参照してください。