词法范围有什么好处?

nbt*_*rap 3 emacs closures elisp emacs24

我不明白为什么Emacs 24的新词法作用域功能如此之好的原因是我想不出任何没有它们就无法实现的新功能.例如,以下闭包:

(setq lexical-binding t)
(defun f1 (num1)
  (lambda (num2)
    (setq num1 (* num1 num2))))

(fset 'f2 (f1 5))
  ==> (closure ((num1 . 5) t) (num2) (setq num1 (* num1 num2)))
(f2 5)
  ==> 25
(f2 2)
  ==> 50
Run Code Online (Sandbox Code Playgroud)

可以使用常规动态范围实现,如下所示:

(defun f1 (num)
  (let ((tmpvar (make-symbol "num")))
    (set tmpvar num)
    `(lambda (num2)
       (set ',tmpvar (* (eval ,tmpvar) num2)))))

(fset 'f2 (f1 5))
  ==> (lambda (num2) (set (quote num) (+ (eval num) num2)))
(f2 5)
  ==> 25
(f2 2)
  ==> 50
(fset 'f3 (f1 9))
  ==> (lambda (num2) (set (quote num) (+ (eval num) num2)))
(f3 3)
  ==> 27
(f3 2)
  ==> 54
(f2 10)
  ==> 500
Run Code Online (Sandbox Code Playgroud)

好的,所以并非所有的语言都有类似于elisp的uninterned符号的东西,所以我理解为什么词法范围在他们的情况下如此之大.但是elisp怎么样?你能想到我现在可以做的任何事情(如Emacs 24),这是我以前做不到的,这要归功于词法范围?

Ste*_*fan 5

你不需要uninterned符号,用cons代替make-symbol,car代替eval和setcar代替的set,你的例子会工作一样好(和更有效).

还要注意,从机器语言到更高级语言的发展主要基于使越来越多的事情变得不可能(或者至少更难).当然,那些远离程序员的设施很少被使用和/或被认为太危险.考虑使用未初始化的变量(可能在C中,但在Java和许多其他语言中不可能),或者跳到指令的中间.

至于你的示例代码的一些缺点:不仅它的可读性较差,而且编译器基本上无法知道你正在构造代码,因此不允许在里面查看"`(lambda .. .)"编译它,扩展它的宏调用,给你关于可疑元素的警告,......