次: Function Forms, 前: Classifying Lists, 上: Forms
リストの先頭要素がシンボルであると、 評価処理ではシンボルの関数セルを調べ、 もとのシンボルのかわりにその内容を使います。 その内容が別のシンボルであると、 シンボルの関数間接(symbol function indirection)と呼ばれる この処理をシンボルでないものを得るまで繰り返します。 シンボルの関数セルに格納された関数名としてのシンボルの使い方について 詳しくは、See Function Names。
この処理の結果、無限ループになる場合もあります。
つまり、シンボルの関数セルが同じシンボルを指している場合です。
あるいは、シンボルの関数セルが空の場合もありえます。
その場合、サブルーティンsymbol-function
は、
エラーvoid-function
を通知します。
いずれの場合でもなければ、最終的にはシンボルでないものを取得し、
それは関数などの適切なオブジェクトであるはずです。
より正確にいえば、Lisp関数(ラムダ式)、バイトコード関数、
基本関数、Lispマクロ、スペシャルフォーム、自動ロードオブジェクトの
いずれかを取得しているはずです。
これらの各種類ごとに、以下の1つ1つの節で説明します。
オブジェクトがこれらのいずれの型でもない場合には、
エラーinvalid-function
を通知します。
つぎの例は、シンボルの関数間接の処理を図示したものです。
fset
を使ってシンボルの関数セルに設定し、
symbol-function
を使って関数セルの内容を取り出します
(see Function Cells)。
具体的には、シンボルcar
をfirst
の関数セルに格納し、
シンボルfirst
をerste
の関数セルに格納します。
;; このような関数セルのリンクを作る
;; ------------- ----- ------- -------
;; | #<subr car> | <-- | car | <-- | first | <-- | erste |
;; ------------- ----- ------- -------
(symbol-function 'car)
=> #<subr car>
(fset 'first 'car)
=> car
(fset 'erste 'first)
=> first
(erste '(1 2 3)) ; erste
が指す関数を呼び出す
=> 1
一方、つぎの例では、シンボルの関数間接を使わずに関数を呼び出します。 というのは、先頭引数はLispの無名関数であって、 シンボルではないからです。
((lambda (arg) (erste arg)) '(1 2 3)) => 1
関数を実行することは、その本体を評価することです。
この過程では、erste
を呼び出すときにシンボルの関数間接が関わります。
組み込み関数indirect-function
は、
明示的にシンボルの関数間接を行う簡単な方法です。