Schemeから入ると, この辺がよくわからなくなります.
#'の正しい呼び方は, "function"です. #'は, その見た目のとおり, functionマクロのリーダマクロでした. functionは, レキシカルクロージャを生成するためのものみたいですね. (Common Lispにおけるlambdaのあれこれ(ありえるえりあ))
しかし, 普通にlambdaと書くだけではクロージャを作らないのかというと, そういうわけでもないようです. 現代におけるCommon Lispのlambdaは, #'(lambda ...)を表すマクロなので, lambdaと書けば, #'(lambda ...)と書いたのと同じだということです. Common Lispで普段使われるlambdaは, 普通のクロージャになるのでしょうか.
関数呼び出しの最左の式(要素?)は, ラムダ抽象か, 関数を束縛した変数である必要があります.
((lambda (x y z ...)) B C ...) ; => ○ ((x y z ...) B C ...) ; (x y z ...)がlambda式でない何か=> × (A B C ...) ; この時, Aは特殊形式 => ○ (A B C ...) ; 関数の名前空間にAの値(関数)が束縛されている => ○ (A B C ...) ; 関数の名前空間にAの値(関数)が束縛されていない => ×上記の○と×は, 文法的かつ変数の束縛している内容について考えた場合, 正しい記述か間違っているかという意味です. Schemeでは上から二番目の(x y z...)も問題ないのですが, Common LispではNG. Common Lispでは, funcallは, この時(or こういった書き方をしたい時)に, 呼ばれる関数のようです. また, 最下段のケースでも, 変数の名前空間でのAに関数が束縛されている時も, funcallが使えます.
これで, なぜfuncallをするのかという謎と, #'の使い所の謎が解けました. lambda抽象に対する#'は不要で, defunで定義した関数について, クロージャを作りたいときに, #'fなどと書けば良いことになります. funcallは, クロージャが渡された時, applyするために使うものとなります.
funcallが必要になるのは, Lisp-2の名前空間が原因のようで, 例えば, (A B C ...)のような関数適用があった時に, 関数の名前空間におけるAが表す値(関数)と変数の名前空間におけるAが表す値(関数/クロージャを1stクラスオブジェクトとして扱えるため)を区別するためにあるようですね.
0 件のコメント :
コメントを投稿