Elisp lambdas,引用和lexical-let

时间:2016-07-26 19:17:27

标签: emacs lambda lisp elisp

我试图理解以下两段代码:

(defun make-adder1 (n) `(lambda (x) (+ ,n x)))

(defun make-adder2 (n) (lexical-let ((n n)) (lambda (x) (+ n x))))

这两者似乎都产生了咔嗒声:

(funcall (make-adder1 3) 5) ;; returns 8
(funcall (make-adder2 3) 5) ;; returns 8

这两个都有效。我有两个主要问题:

1)我不理解"引用级别"这两种方法之间。在第一种情况下,引用lambda表达式,这意味着"符号本身"返回而不是值。在第二种情况下,似乎将对lambda的语句进行求值,因此将返回lambda的值。然而,这些都与funcall一起使用。在funcall' ed函数上使用defun时,必须引用它。词汇 - 让我自动做某种引用吗?不是吗,有点令人惊讶吗?

2)阅读关于这个主题的其他帖子,我了解到第一种方法在某些情况下会崩溃,并且偏离了人们对使用lambda和其他语言中的高阶函数的期望,因为elisp默认具有动态范围。有人能给出一个具体的代码示例,使这种差异显而易见并解释它吗?

1 个答案:

答案 0 :(得分:2)

在第一个示例中,结果函数中没有变量n,只有(lambda (x) (+ 3 x))。它不需要词法绑定,因为lambda中没有自由变量,即没有需要保存在闭包绑定中的变量。如果您不需要变量n可用,作为变量使用该函数,即,如果它在函数定义时间(= 3)的值是您需要的全部内容,那么第一个例子就是你所需要的。

(fset 'ad1 (make-adder1 3))

(symbol-function 'ad1)

返回:

(lambda (x) (+ 3 x))

第二个例子创建了一个实际上是创建和应用复杂闭包的函数。

(fset 'ad2 (make-adder2 3))

(symbol-function 'ad2)

返回

(lambda (&rest --cl-rest--)
  (apply (quote (closure ((--cl-n-- . --n--) (n . 3) t)
                         (G69710 x)
                         (+ (symbol-value G69710) x)))
         (quote --n--)
         --cl-rest--))

第三种选择是使用lexical-binding文件局部变量并使用最直接的定义。这会创建一个简单的闭包。

;;; foo.el --- toto -*- lexical-binding: t -*-
(defun make-adder3 (n) (lambda (x) (+ n x)))

(fset 'ad3 (make-adder3 3))

(symbol-function 'ad3)

返回:

(closure ((n . 3) t) (x) (+ n x))
(symbol-function 'make-adder1)

返回:

(lambda (n)
  (list (quote lambda)
    (quote (x))
    (cons (quote +) (cons n (quote (x))))))


(symbol-function 'make-adder2)

返回:

(closure (t)
     (n)
     (let ((--cl-n-- (make-symbol "--n--")))
       (let* ((v --cl-n--)) (set v n))
       (list (quote lambda)
         (quote (&rest --cl-rest--))
         (list (quote apply)
           (list (quote quote)
             (function
              (lambda (G69709 x)
                (+ (symbol-value G69709) x))))
           (list (quote quote) --cl-n--)
           (quote --cl-rest--)))))


(symbol-function 'make-adder3)

返回

(closure (t) (n) (function (lambda (x) (+ n x))))