lexical-binding和closure的问题


#1

首先lexical-binding没问题

(lambda (seq) (cdr seq))
;;=> (closure (t) (seq) (cdr seq))

我以为会返回1,因为我把cdr的函数设为了car:

(funcall (cl-letf (((symbol-function 'cdr) (symbol-function 'car))
                   ((symbol-function 'car) (symbol-function 'cdr)))
           (lambda (seq)
             (cdr seq)))
         '(1 . 2))
;;=> 2

直接用没问题:

(cl-letf (((symbol-function 'cdr) (symbol-function 'car))
          ((symbol-function 'car) (symbol-function 'cdr)))
  (cdr '(1 . 2)))
;;=> 1

closure是这样的:

(cl-letf (((symbol-function 'cdr) (symbol-function 'car))
          ((symbol-function 'car) (symbol-function 'cdr)))
  (lambda (seq)
    (cdr seq)))

(closure ((old . #<subr cdr>) (old . #<subr car>) (vnew . #<subr cdr>) (vnew . #<subr car>) t) (seq) (cdr seq))

P.S. 据文档说,((old . #<subr cdr>) (old . #<subr car>) (vnew . #<subr cdr>) (vnew . #<subr car>) t)lexical environment,但我看不出来是怎么用的。

是我对closure有什么误解么?


#2

Closure 的环境中仅支持普通的变量,一般能直接用 let 设置,不支持用 cl-letf 设置的 Generalized Variable

;; -*- lexical-binding: t; -*-
(let ((cdr #'car))
  ((lambda ()
     (funcall cdr (cons 1 2)))))
;; => 1

至于你的例子,你得把 cl-letf 放到 lambda 里面,而不能依赖 Lexical Binding / Closure。