为什么funcall忽略词汇范围?
这个旧答案中的代码让我很兴奋,解释了为什么需要用引号引起来,但是我却不这样做不明白为什么funcall
似乎跳过了通常的范围规则.
I'm piqued by the code in this old answer explaining why sharp quote is needed, but what I don't understand is why funcall
seems to skip the usual scope rules.
(defun test () 'red)
(flet ((test () 'green))
(list (funcall 'test)
(funcall #'test))) => (red green)
我是否应该将Common Lisp理解为具有由let-family函数设置的局部"词法范围的符号绑定和由de- Family函数设置的全局范围的变量符号绑定?
Should I understand Common Lisp as having both "local" lexically scoped symbol bindings as set by let-family functions and globally scoped variables symbol bindings as set by de- family functions?
假定使用通用Lisp.
Common Lisp is assumed.
DEFUN和朋友
DEFUN创建一个 global 函数绑定,该绑定可以通过符号检索.
DEFUN creates a global function binding, which can retrieved via symbols.
(defun foo () 'foo)
上面有一个函数FOO.
Above we have a function FOO.
我们叫它:
(funcall (function foo)) ; no lexical bound function available, so it uses
; the symbol's binding
或
(funcall (symbol-function 'foo))
或
(funcall 'foo)
或
(foo)
以上所有功能都具有相同的功能.
All above access the same function.
注意:上面显示了(foo)
和(funcall 'foo)
调用相同的函数.有一个例外:文件编译器可能会假定函数FOO
不变.这使Lisp编译器可以内联代码或编译为更快的函数调用代码.如(funcall 'foo)
所示,通过符号调用函数总是导致对当前和最新绑定的调用-因此始终需要通过符号进行查找.
Note: above shows that (foo)
and (funcall 'foo)
calls the same function. There is an exception: a file compiler may assume that a function FOO
does not change. This allows a Lisp compiler to inline code or to compile to faster function calling code. Calling the function via the symbol as in (funcall 'foo)
always results in a call to the current and latest binding - thus a lookup via the symbol is always needed.
FLET和标签
FLET和LABELS创建按词法界定的函数绑定. FUNCTION
可以引用这样的绑定.请注意,在运行时无法通过符号访问这些绑定.只有两种方法:
FLET and LABELS create lexically scoped function bindings. FUNCTION
can reference such a binding. Note that these bindings can't be accessed via symbols at runtime. There are only two ways:
-
调用函数
(foo)
.
通过(function foo)
引用该函数.
由于两者都使用静态词法引用,因此在运行时不会通过符号或类似内容进行查找.这意味着符号在运行时不会与词法函数相关,它们仅在源代码中可见.
Since both are using static lexical references, there is no lookup at runtime via symbols or similar. That means, symbols are not involved at runtime with lexical functions - they are only visible in the source code.
(flet ((foo () 'bar)) ; <- local lexical scope, function binding
(foo) ; calls the lexical bound function foo
或
(funcall (function foo)) ; calls the lexical bound function foo
但是
(funcall (symbol-function 'foo)) ; calls the symbol's binding,
; not the lexical binding
和
(funcall 'foo) ; calls the symbol's binding
; not the lexical binding
)