次: , 前: Lambda Expressions, 上: Functions


11.3 関数を命名する

ほとんどの計算機言語では、各関数には名前があります。 名前のない関数という考えは本質的ではありません。 Lispでは、もっとも厳密にいえば、関数には名前はありません。 関数は、先頭要素が単にlambdaであるリスト、 バイトコード関数オブジェクト、あるいは、基本関数のsubrオブジェクトです。

しかしながら、シンボルは関数の名前として働きます。 シンボルの関数セル(function cell、see Symbol Components)に 関数を入れると、このようになります。 そうすると、シンボルそのものは正当な呼び出し可能な関数となり、 関数セルが参照するリストやsubrオブジェクトと等価になります。 関数セルの内容をシンボルの関数定義(function definition)とも呼びます。 シンボルのかわりにシンボルの関数定義を使う処理を シンボルの関数間接(symbol function indirection)と呼びます。 See Function Indirection

実用上、ほとんどすべての関数には、このようにして名前が付いていて、 その名前で参照します。 たとえば、シンボルcarは、 その関数セルに基本関数のsubrオブジェクト#<subr car>が格納してあるので、 その動作を行う関数として動作します。

関数に名前を与えるのは、Lisp式からその名前で参照できると便利だからです。 #<subr car>のような基本関数のsubrオブジェクトでは、 名前はそれらを参照する唯一の方法です。 そのようなオブジェクトには入力構文はありません。 Lispで書いた関数では、明示的なラムダ式より名前を使うほうがより便利です。 また、関数に名前があればそれを参照できます。 つまり、再帰呼び出しができます。 関数の名前をその定義そのものに書くことは、 関数定義がそれ自身を指すようにする (これは不可能ではないにしても、実用上はさまざまな欠点がある)よりは、 とても便利です。

関数を指名するシンボルで関数をしばしば識別します。 たとえば、しばしば『関数car』といって、 シンボルcarと関数定義である基本関数のsubrオブジェクトとを区別しません。 ほとんどの目的には、区別する必要はありません。

たとえそうであっても、関数に一意な名前は必要ないことを 心に留めておいてください。 関数オブジェクトは普通1つのシンボルの関数セルだけに現れますが、 これは単なる便法です。 fsetを使って、複数のシンボルに格納するのは簡単です。 そうすると、各シンボルは同じ関数を同等に指名します。

関数名として使うシンボルは、変数としても使えます。 シンボルのこれら2つの使い方は独立していて衝突しません。 (SchemeなどのLispの方言のなかには、 シンボルの値とその関数定義を区別しないものもある。 変数としてのシンボルの値は、その関数定義でもある。) シンボルに関数定義を与えていないと、そのシンボルを関数としては使えません。 これは、シンボルに変数としての値があるかどうかには関係しません。