10

我创建了一个在 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)

由于Lisp-1 和 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: capture variable from inner function了解到这是由于 Emacs Lisp 的动态绑定。

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

相关问题:

4

3 回答 3

11

NEWSEmacs 24 开始:

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)
于 2012-10-07T20:55:46.557 回答
6

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

使用假闭包,和lexical-let.

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

Richard Stallman在不久前写的一篇论文中回答了这个问题。

于 2012-10-07T20:32:44.600 回答
3
(defun singleton-set (elem)
  `(lambda (n) (= n ,elem))

参见:elisp 函数作为参数和返回值

于 2012-10-07T20:30:16.340 回答