【问题标题】:Elisp extend variable lifetimeElisp 延长变量寿命
【发布时间】:2020-02-16 18:47:19
【问题描述】:

我有一个循环,我在每次迭代期间创建一个局部变量。然后我声明了一个 lambda,它在将来的某个时间使用局部变量。

      (dolist (entry (read-lines "~/.emacs-projects"))
         (let ((project (car (json-read-from-string entry)))) ;; <---- I NEED THIS ONE
             (widget-create 'link
                     :button-prefix ""
                     :button-suffix ""
                     :action (lambda (wid &rest ignore) (load-project project)) ;; HERE
                     (format "%s : %s\n" (car project) (cdr project)))))

在上面的代码中,我创建了project,当:action 触发时,我想使用project 作为另一个函数的参数。目前,当运行 lambda 时,我得到了Symbol’s value as variable is void: project,这让我认为外部范围没有被保留。

如何延长project 的生命周期,以便在 lambda 中访问它?

【问题讨论】:

  • 您正在寻找一个 closure(或类似物)。这是多年来 elisp 的一个常见问题,因此使用该术语进行搜索将获得结果(注意其中一些将早于词法绑定的可用性)。

标签: variables emacs lexical-scope


【解决方案1】:

您想使用 Emacs Lisp 的词法范围风格,这是 Emacs-24 中添加的主要新功能之一。为此,只需在 Elisp 文件的第一行的某处(通常在注释中)添加以下内容:

-*- lexical-binding:t -*-

希望在未来的某个时候,旧的动态范围方言将不再是默认的。

【讨论】:

    【解决方案2】:

    要么使用词法范围(非nil variable lexical-binding),要么使用project 的值替换变量本身的列表lambda 形式:

     (dolist (entry (read-lines "~/.emacs-projects"))
             (let ((project (car (json-read-from-string entry)))) ;; <---- I NEED THIS ONE
                 (widget-create 'link
                         :button-prefix ""
                         :button-suffix ""
                         :action `(lambda (wid &rest ignore) (load-project ',project)) ;; HERE
                         (format "%s : %s\n" (car project) (cdr project)))))
    

    如果你的动作函数并不真正需要project作为变量,但它只需要它的值,那么你可以直接替换这个值,如图所示。

    但在这种情况下,您的 lambda 表单将是一个列表(其汽车为 lambda 等),因此在评估之前不会被识别为函数。特别是,字节编译器只会将其视为一个列表,而不是一个函数。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-07-15
      • 2011-06-07
      • 1970-01-01
      • 2012-06-03
      • 1970-01-01
      • 1970-01-01
      • 2019-04-03
      相关资源
      最近更新 更多