为什么 Common Lisp 函数在封闭的 let 之外可见?

Why are Common Lisp functions visible outside an enclosing let?

在 Scheme 中,下面的函数 f 在其封闭 let:

之外是不可见的
(let ()
  (define (f x)
    (+ x 1)))

(f 2)  ; Error.

然而,在 Common Lisp 中,函数 f 在其封闭 let:

之外是可见的
(let ()
  (defun f (x)
    (+ x 1)))

(f 2)  ; Returns: 3

上面的 Common Lisp 代码是怎么回事? f 如何在 let 之外可见?

来自普通的 lisp hyperspec:

计算 defun 导致函数名成为 lambda 表达式指定的函数的全局名称

 (lambda lambda-list
   [[declaration* | documentation]]
   (block block-name form*))

在执行 defun 的词法环境中处理。

http://www.lispworks.com/documentation/HyperSpec/Body/m_defun.htm#defun

如果您想要本地定义,请使用 fletlabels

在方案的情况下,define 在定义它的 <body> 中是局部的。

在 Scheme 中,define 运算符可用于顶级定义 用于内部定义。对于内部定义,这些应该出现在 body 的开头,它的效果类似于 letrec* 形式。请参阅 R7RS 中的第 5.3 章。

在 Common Lisp 中 defun 总是定义一个全局函数。为了定义局部词法函数,Common Lisp 还有两个其他运算符:fletlabelslabels 用于递归函数。