局部于 `let` 与局部于函数

Local to `let` versus local to a function

中,关于Elisp中的局部变量定义,两位受访者都建议let是合适的,并强调它不会将变量定义为函数的局部变量。该变量仅对 let 语句是局部的。

local to let 和 local to the function 有什么区别?是否有另一种结构可以为函数的范围定义变量?

使用 let 语句的函数如下所示:

(defun test-search (string)
  "Searches for STRING in document.
Displays message 'Found!' or 'Not found...'. Places point after word 
when found; fixed otherwise."
  (interactive "sEnter search word: ")
  (let ((found (save-excursion
         (beginning-of-buffer)
         (search-forward string nil t nil))))
    (if found
        (progn
          (goto-char found)
          (message "Found!"))
      (message "Not found..."))))

由于 let 在您的示例中构成了整个函数,因此您的 "variables local to let" 与 "variables local to the function" 没有区别。

因此,没有单独的构造来引入函数的局部变量。 let 是该构造,可用于对整个函数有效的变量,或对小子集有效的变量,具体取决于您放置 let.

的位置

What is the distinction between local to let and local to the function?

这个问题的解释有点开放,但在这里我将 "local to the function" 解释为不是 函数 一部分的代码看不到变量,并且默认情况下 在 Emacs 中 let 绑定不是这种情况(或者实际上对于一般的变量绑定)。

要详细了解,您需要了解 动态绑定 词法绑定 之间的区别(其他地方对此有很好的解释,所以你可以自己跟进)。但是,为了简要说明差异,请考虑以下函数:

(defun func1 ()
  (let ((foo 42))
    (func2)))

(defun func2 ()
  (bound-and-true-p foo))

func1的结果是func2的结果,这又取决于一个变量foo是否对后一个函数可见

默认动态绑定下,调用func1会return42,因为foo的绑定范围是let的持续时间],其中包含对 func2.

的调用

在词法绑定下,调用 func1 将 return nil,因为 foo(尚未声明为动态的)有一个绑定到 func1 因此 func2 看不到它)。

关于上面的例子,我在谈论 "local to the function" 时实际上有点误导,因为 foo 绑定的范围严格来说是 let 形式的范围而不是 函数 的范围。但是,该行为不仅限于 let 绑定,因此我们还可以使用以下示例,比较 (func3 42) 在动态和词法绑定下的结果:

(defun func3 (foo)
  (func4))

(defun func4 ()
  (bound-and-true-p foo))