为什么funcall忽略词汇范围? [英] Why does funcall ignore the lexical scope?

查看:66
本文介绍了为什么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

)      

这篇关于为什么funcall忽略词汇范围?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆