【问题标题】:Higher-order functions in ElispElisp 中的高阶函数
【发布时间】:2012-09-28 03:50:09
【问题描述】:

我在 Elisp 中创建了一个返回函数的函数:

(defun singleton-set (elem)
  (defun f (n) (= n elem))
  f)

我尝试在 IELM 中运行它,但它失败了:

ELISP> (singleton-set 5)
*** Eval error ***  Symbol's value as variable is void: f
ELISP> ((singleton-set 5) 5)
*** Eval error ***  Invalid function: (singleton-set 5)

由于What is the difference between Lisp-1 and Lisp-2?我把代码改成了

(defun singleton-set (elem)
  (defun f (n) (= n elem))
  #'f)

并调用(funcall (singleton-set 5) 5),但现在错误是

*** Eval error *** Symbol's value as variable is void: elem

我从elisp: capturing variable from inner function 了解到,这是由于 Emacs Lisp 的动态绑定造成的。

如何在 Emacs Lisp 中使函数返回函数成为可能?这种机制与 Python、Scala 或 Clojure 等其他语言不同的原因是什么?

相关问题:

【问题讨论】:

标签: emacs elisp higher-order-functions dynamic-binding


【解决方案1】:

来自 Emacs 24 的 NEWS

Emacs 24.1 中的 Lisp 变化

  • 代码现在可以默认使用词法范围而不是动态范围。 lexical-binding 变量为本地启用词法范围 变量。它通常通过第一个文件局部变量设置 文件的行,在这种情况下,它适用于该文件中的所有代码 文件。

所以,在 Emacs 24 中:

(setq lexical-binding t)
(defun singleton-set (elem) (lambda (n) (= n elem)))
(mapcar (singleton-set 1) '(0 1 2 3))
    ===> (nil t nil nil)

【讨论】:

  • 这对我来说似乎没有使用词法绑定——也许我错过了一些东西。我在代码中没有看到任何类型的闭包。
  • @CharlieFlowers:你错过了一些东西。 (尝试打开和关闭lexical-binding,你会看到。)如果lambda 要在对singleton-set 的调用之外被调用,elem 需要被词法绑定。
【解决方案2】:

如何在 Emacs Lisp 中让函数返回函数成为可能?

使用fake closureslexical-let

这种机制与 Python、Scala 或 Clojure 等其他语言不同的原因是什么?

Richard Stallman answered this question 在他不久前写的一篇论文中。

【讨论】:

    【解决方案3】:
    (defun singleton-set (elem)
      `(lambda (n) (= n ,elem))
    

    见:elisp functions as parameters and as return value

    【讨论】:

      猜你喜欢
      • 2016-05-07
      • 2011-07-16
      • 2021-02-01
      • 2023-03-18
      • 1970-01-01
      相关资源
      最近更新 更多