请教 Macro 的参数 eval 问题. lambda 表达式相关。

不是完全透明的,我以前找到过反例

不过我当时对 lisp 理解还不够,这样写就可以了

(let ((p '(x . 1)))
  (setq foo
        `(closure (,p t) (y)
                  (setq x y)))
  (setq bar
        `(closure (,p t) ()
                  x)))

(funcall foo 2)
;; 2

bar
;; (closure ((x . 2) t) nil x)

(funcall bar)
;; 2

Emacs Lisp 的 printer 本身对 sharing 就不是很透明。

(setq print-circle t)

foo
;; (closure ((x . 2) t) (y) (setq x y))
(list foo bar)
;; ((closure (#1=(x . 2) t) (y) (setq x y)) (closure (#1# t) nil x))

SBCL 的设计是只有 compiler,没有 interpreter,所有对 eval 的调用是 just in time compile。这样就没有不一致的问題。然后因为和 CLOS MOP 的 funcallable instance 设计冲突没有透明的 closure 实现也很正常。

有些比较简易的 Scheme 的 closure 实现是透明的。我记很 festival TTS 用的 Scheme 就是这样 https://www.cstr.ed.ac.uk/projects/festival/manual/

Emacs Lisp 的 byte-compile 需要利用 lexical scoping 的 renaming 去除局部变量来相对 dynamic scoping 提高运行效率。

1 个赞