2008年12月26日金曜日

'fooと#'fooの違いは環境の違い

QUOTEとFUNCTIONを使い分ける:もう少し詳しい説明 -- 逆引きCommonLisp

をぼんやり見ていて、そういえば FUNCTION と COERCE では環境が違うってうちの CLISP が言ってたのを思い出した。

(funcall '(lambda (x) (1+ x)) 1)
;; => Error
;; *** - FUNCALL: argument (LAMBDA (X) (1+ X)) is not a function.
;;       To get a function in the current environment, write (FUNCTION ...).
;;       To get a function in the global environment, write (COERCE '... 'FUNCTION).

CLHS にもそれらしい記述があったのでメモ。

CLHS: Function COERCE
If the result-type is function, and object is any function name that is fbound but that is globally defined neither as a macro name nor as a special operator, then the result is the functional value of object. If the result-type is function, and object is a lambda expression, then the result is a closure of object in the null lexical environment.

= objectがマクロ、スペシャル・オペレータ以外でグローバルに定義されたfboundな関数名を持っているなら、そのobjectの関数値を返す。 objectがラムダ式なら、空レキシカル環境なobjectのクロージャを返す。

CLHS: Special Operator FUNCTION
The value of function is the functional value of name in the current lexical environment.

= functionは現在のレキシカルな環境を持ったnameの関数値を返す。

この環境を引数に渡せる関数、マクロはいくつかある。 ラムダリストキーワードに &environment を持つものがそれで、例えば setf とか push とか。

(arglist 'setf)
;=> (&WHOLE SYSTEM::WHOLE-FORM &REST SYSTEM::ARGS &ENVIRONMENT SYSTEM::ENV)

macroexpand も環境を引数に渡せるが、こちらはなぜか &optional になっている。

(arglist 'macroexpand)
;=> (FORM &OPTIONAL ENV)

0 件のコメント:

コメントを投稿