在emacs24词汇EVAL(Lexical eval in emacs24)

2019-06-25 12:52发布

任何人都可以解释我是如何eval可与emacs24? 从eval描述:

eval is a built-in function in `C source code'.

(eval FORM &optional LEXICAL)

Evaluate FORM and return its value.
If LEXICAL is t, evaluate using lexical scoping.

这是否意味着,这样的事情应该工作?

(setq lexical-binding t)
(let ((myvarr 42)) (eval 'myvarr t)) ; (void-variable myvarr)

更新:

(setq lexical-binding nil)
;; => nil
(let ((myvarr 42)) (eval 'myvarr))
;; => 42 (#o52, #x2a, ?*)
(setq lexical-binding t)
;; => t
(let ((myvarr 42)) (eval 'myvarr))
;; Debugger entered--Lisp error: (void-variable myvarr)
;;   eval(myvarr)
;;   (let ((myvarr 42)) (eval (quote myvarr)))
;;   (progn (let ((myvarr 42)) (eval (quote myvarr))))
;;   eval((progn (let ((myvarr 42)) (eval (quote myvarr)))) t)
;;   eval-last-sexp-1((4))
;;   eval-last-sexp((4))
;;   call-interactively(eval-last-sexp nil nil)
;;   call-last-kbd-macro(nil kmacro-loop-setup-function)
;;   kmacro-call-macro(nil nil)
;;   kmacro-end-or-call-macro(nil)
;;   call-interactively(kmacro-end-or-call-macro nil nil)
(ignore-errors (let ((myvarr 42)) (eval 'myvarr)))
;; => nil
(setq lexical-binding nil)
;; => nil
(eval (let ((myvarr 42)) (eval 'myvarr)) t)
;; => 42
(eval '(let ((myvarr 42)) (eval 'myvarr)) t)
;; Debugger entered--Lisp error: (void-variable myvarr)
;;   eval(myvarr)
;;   (let ((myvarr 42)) (eval (quote myvarr)))
;;   eval((let ((myvarr 42)) (eval (quote myvarr))) t)
;;   eval((eval (quote (let ((myvarr 42)) (eval (quote myvarr)))) t) nil)
;;   eval-last-sexp-1((4))
;;   eval-last-sexp((4))
;;   call-interactively(eval-last-sexp nil nil)

Emacs的版本: GNU Emacs 24.1.1 (i386-mingw-nt6.1.7600) of 2012-06-10 on MARVIN

Answer 1:

由于词汇绑定符太多现有的elisp的代码,它是一个可选功能。

词法作用域可以最好地用一个简单的例子理解:

(defun some-func (callback)
 (let ((a 5))
  (funcall callback)))

(let ((a 3))
 (some-func (lambda () a)))

在大多数语言中,这将返回3,因为asome-func似乎从底部形态不可见。 然而,在24之前的emacs或不词法作用域此程序返回5。

这导致许多意想不到的惊喜和交互功能之间微妙而往往是隐藏的bug; 解决这个问题的emacs 24介绍词汇范围,但正如前面提到的,是向后兼容的。

的机制来选择在对动态作用域是任一文件变量lexical-binding (其打开它每个源文件),或者作为选择你看到eval

因此,如果我们重写例如使用eval

(eval '(let ((a 3))
        (some-func (lambda () a))) nil) ; => 5

(eval '(let ((a 3))
        (some-func (lambda () a))) t) ; => 3

在你的榜样,是什么让差异并不里面的代码是否eval动态范围的,但围绕它的代码是。 变量绑定是什么是词法范围,而不是变量查找影响。 我不能完全肯定的eval的语义在这里,但似乎是发生(什么是最有意义的)是eval评估了一个全新的词汇中,表述。 因此,外部词汇范围是从内部隐藏eval ,但动态范围仍清晰可见(这样查找成功时,文件是动态范围的,而不是其他)。



Answer 2:

我找不到的形式语义eval在Emacs 24的功能,但所有的假设例子时,它的作品以同样的方式为Common Lisp中(由cobbal所示)是有意义的。 在Common Lisp的HyperSpec说:

句法:

eval 形式

描述:

评估当前的动态环境和词法环境 形式

让我们来看看你的例子一个接一个在头脑里的描述。

(setq lexical-binding t)
(let ((myvarr 42)) (eval 'myvarr t)) ; Lisp error: (void-variable myvarr)

词法结合是通过设置启用tlexical-binding ,所以myvarr变成是词法绑定变量,这是不可用的内部eval如上所述的功能。 该eval功能的选项, t ,在这里无关紧要。

(setq lexical-binding nil)
(let ((myvarr 42)) (eval 'myvarr)) ; 42

词法绑定是通过设置禁用nillexical-binding ,所以myvarr变成是一个动态绑定的变量,它是可用的内部eval功能。 该eval功能的选项,implicilty nil ,在这里无关紧要。

(setq lexical-binding t)
(let ((myvarr 42)) (eval 'myvarr)) ; Lisp error: (void-variable myvarr)

词法结合是通过设置启用tlexical-binding ,所以myvarr变成是词法绑定变量,这是不可用的内部eval功能。 该eval功能的选项,implicilty nil ,在这里无关紧要。

(ignore-errors (let ((myvarr 42)) (eval 'myvarr))) ; nil

同上。

(setq lexical-binding nil)
(eval (let ((myvarr 42)) (eval 'myvarr)) t) ; 42

词法结合被设置禁用nillexical-binding ,所以myvar变成是一个动态绑定的变量,它是可用的内内部eval功能。 请注意, let形式使用,包括内部eval功能时,作为参数评价制备的外之前eval被调用。 无论是外部还是内部eval函数的选择是relevenat这里。

(eval '(let ((myvarr 42)) (eval 'myvarr)) t) ; Lisp error: (void-variable myvarr)

myvarr变成是词法绑定变量,这是不可用的内里eval 。 需要注意的是,由于'中, let形式是由外部评估eval用词汇绑定功能启用。 外eval函数的选择就是与此有关,而内部eval函数的不是。


为什么空词法环境?

也就是说,我认为,因为如果当前词法环境中使用的字母等值将不再举行。

阿尔法等价是说的函数的参数名称并不重要正式的方式。 例如, (lambda (x) x)(lambda (y) y)是α-等效,而且我们已经把它们看作是相同的。 阿尔法等价使我们能够改变一个函数参数的名称,因为我们希望在任何时间。 我们认为理所当然,我们会如果它不持有很惊讶。 见LAMBDA演算和阿尔法等价的更正式的解释。

但阿尔法等价结果有当涉及自由变量(称为开放代码)代码值可以作为周围用Lisp传递一些问题。 让我们来看看下面的例子:

;;; -*- lexical-binding: t -*-
(lambda (x) (lambda (y) (eval x))) '(1+ y)

如果eval当前词法环境下评估时,表单将相当于(lambda (y) (1+ y)) 。 现在看下面的程序:

(lambda (x) (lambda (z) (eval x))) '(1+ y)

这个程序是从以前的一个只有在它的参数的名称,不同的z代替y ,所以我们自然期望他们以同样的方式行事。 但后者程序的计算结果为(lambda (z) (1+ y))这是绝对不同(lambda (y) (1+ y)想想当得到的函数值应用到同样的参数会发生什么该点是一个函数参数的名称时,允许含有自由变量的代码值物质DOES。

在这里,我们有两个选择,以保持字母等价的:我们不能放弃的α等价,因为它感觉那么自然,我们一直如此多的习惯了。 第一个选项是已经eval空词法环境下评价为(公用)Lisp的一样。 使用此选项,自由变量y(1+ y)不绑定到形式参数y(lambda (y) ...) 所以,这两个程序行为一致和α-等价保存完好。 另一个选择是不容许从一开始就开放代码值来排除问题。 我听说,这是由所选择的方法MetaOCaml

有人可能会问:“如果是这样,为什么目前的动态环境?”。 对于动态绑定(又名特)变量,我们已经认识清楚,他们的名字是如此的重要,并且,如果你不小心改变它们,你的程序将被打破。



Answer 3:

你内心的古怪行为eval形式似乎类似的symbol-valueadd-to-list下的词汇绑定。

emacs的词法作用域和引用变量

  • 下词法结合,一个符号的值细胞仅持有全局值,(其可以是从变量的词法结合值不同)。

  • 引用变量的使用(如(eval 'var) (eval '(print var)) (add-to-list 'var 1)仅获得或符号的值电池中。

实践以避免遇到这种疑难杂症有:

  • 尝试定义和使用宏,而不是EVAL尽可能

  • 如果你想创建/声明一个全局变量,使用避免setq来创建它,使用defvardefcustomdefconst将其创建为一个特殊的变量来代替。 特殊变量总是动态范围的,甚至在词汇结合模式。



文章来源: Lexical eval in emacs24