lisp - 为什么 funcall 会忽略词法作用域?

标签 lisp common-lisp

我被 this old answer 中的代码激怒了解释为什么需要尖锐的引用,但我不明白的是为什么 funcall 似乎跳过了通常的范围规则。

(defun test () 'red)

(flet ((test () 'green))
  (list (funcall 'test)
        (funcall #'test))) => (red green)

我是否应该将 Common Lisp 理解为具有由 let-family 函数设置的“本地”词法范围符号绑定(bind)和由 de-family 函数设置的全局范围变量符号绑定(bind)?

最佳答案

假定使用 Common Lisp。

DEFUN 和 friend 们

DEFUN 创建一个全局 函数绑定(bind),可以通过符号检索。

(defun foo () 'foo)

上面我们有一个函数 FOO。

我们称它为:

(funcall (function foo))   ; no lexical bound function available, so it uses
                           ; the symbol's binding

(funcall (symbol-function 'foo))

(funcall 'foo)

(foo)

以上所有访问相同的功能。

注意:上面显示 (foo)(funcall 'foo) 调用相同的函数。有一个异常(exception):文件编译器可能假定函数 FOO 不会改变。这允许 Lisp 编译器内联代码或编译为更快的函数调用代码。通过 (funcall 'foo) 中的符号调用函数总是会导致调用当前和最新的绑定(bind) - 因此始终需要通过符号进行查找。

FLET 和标签

FLET 和 LABELS 创建词法作用域的函数绑定(bind)。 FUNCTION 可以引用这样的绑定(bind)。请注意,无法在运行时通过符号访问这些绑定(bind)。只有两种方式:

  • 调用函数(foo)

  • 通过(function foo)引用函数。

由于两者都使用静态词法引用,因此在运行时不会通过符号或类似方式进行查找。这意味着,符号在运行时不涉及词法函数——它们只在源代码中可见。

(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

)      

关于lisp - 为什么 funcall 会忽略词法作用域?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29337947/

相关文章:

lisp - 如何使用不对称(未配对)的任意括号创建宏

scheme - 帮助理解 Scheme 中的 Continuations

multidimensional-array - 在 Common Lisp 中实现多维关联数组

common-lisp - 使用 Ironclad 和 Flexi-stream 进行哈希处理

lisp - 如何判断列表是否包含 NIL?

lisp - 是否存在可设置的 nthcdr 实现?

reflection - 在 Common Lisp 中拦截和修改用户输入

list - 如何找到多级列表的长度?

function - 使用不同的表达式系统地调用 Common Lisp 宏

lisp - Common Lisp 函数可以按位置或关键字接受参数吗?