首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Elisp lambdas、quoting和lexical-let

Elisp lambdas、quoting和lexical-let
EN

Stack Overflow用户
提问于 2016-07-27 03:17:27
回答 1查看 360关注 0票数 0

我正在尝试理解以下两个代码片段:

代码语言:javascript
复制
(defun make-adder1 (n) `(lambda (x) (+ ,n x)))

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

这两个似乎都会产生可伸缩代码:

代码语言:javascript
复制
(funcall (make-adder1 3) 5) ;; returns 8
(funcall (make-adder2 3) 5) ;; returns 8

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

1)我不理解这两种方法在“引用级别”上的差异。在第一种情况下,lambda表达式被引用,这意味着返回的是“符号本身”,而不是值。在第二种情况下,似乎包含lambda的语句将被计算,因此将返回lambda的值。然而,这两种方法都适用于funcall。当在defun'ed函数上使用funcall时,它必须被引用。lexical-let会自动进行某种引用吗?这不是有点令人惊讶吗?

2)阅读关于这个主题的其他文章,我了解到第一种方法在某些情况下会失败,并与使用lambda和其他语言的高阶函数时的预期背道而驰,因为elisp默认情况下具有动态作用域。有没有人能给出一个具体的代码例子,让这种差异变得明显,并解释一下?

EN

回答 1

Stack Overflow用户

发布于 2016-07-27 09:12:59

在第一个示例中,结果函数中没有变量n,它只是(lambda (x) (+ 3 x))。它不需要词法绑定,因为lambda中没有自由变量,也就是说,闭包的绑定中没有需要保留的变量。如果在使用函数时不需要变量n可用,也就是说,如果在函数定义时它的值(=3)就是您所需要的,那么您只需要第一个示例。

代码语言:javascript
复制
(fset 'ad1 (make-adder1 3))

(symbol-function 'ad1)

返回:

代码语言:javascript
复制
(lambda (x) (+ 3 x))

第二个示例实际上创建了一个函数,它创建并应用了一个复杂的闭包。

代码语言:javascript
复制
(fset 'ad2 (make-adder2 3))

(symbol-function 'ad2)

返回

代码语言:javascript
复制
(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文件局部变量,并使用最直接的定义。这将创建一个简单的闭包。

代码语言:javascript
复制
;;; foo.el --- toto -*- lexical-binding: t -*-
(defun make-adder3 (n) (lambda (x) (+ n x)))

(fset 'ad3 (make-adder3 3))

(symbol-function 'ad3)

返回:

代码语言:javascript
复制
(closure ((n . 3) t) (x) (+ n x))

代码语言:javascript
复制
(symbol-function 'make-adder1)

返回:

代码语言:javascript
复制
(lambda (n)
  (list (quote lambda)
    (quote (x))
    (cons (quote +) (cons n (quote (x))))))


(symbol-function 'make-adder2)

返回:

代码语言:javascript
复制
(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)

返回

代码语言:javascript
复制
(closure (t) (n) (function (lambda (x) (+ n x))))
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/38598176

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档