从闭包创建实例

Create an instance from a closure

我正在阅读示例3.1Assignment and Local State from SICP

#+begin_src scheme 
(define (make-withdraw balance)
  (lambda (amount)
    (if (>= balance amount)
        (begin (set! balance (- balance amount))
               balance)
        "Insufficient funds")))
(define W1 (make-withdraw 100))
(W1 50)
(W1 30)
#+end_src

#+RESULTS:
: 20

用 elisp 练习

#+begin_src emacs-lisp lexical t
(defun make-withdraw(balance)
  (lambda (amount)
    (if (>= balance amount)
        (progn (setq balance (- balance amount))
               balance)
        "Insufficient funds")))
(make-withdraw 10)
(defvar W1 (make-withdraw 100))
(funcall (W1 30))
#+end_src

#+RESULTS:
: W1

没有按预期工作,交互试验

情况 1:直接调用 make-withdraw 和 return 闭包

;; lexical-binding t 
ELISP> (make-withdraw 100)
(closure
 ((balance . 100)
  t)
 (amount)
 (if
     (>= balance amount)
     (progn
       (setq balance
             (- balance amount))
       balance)
   "Insufficient funds"))

情况 2:将其分配给 W1,但 return 是一个普通函数而不是闭包

ELISP> (defvar W1 (funcall (withdraw 100)))
W1
ELISP> W1
(lambda
  (amount)
  (if
      (>= balance amount)
      (progn
        (setq balance
              (- balance amount))
        balance)
    "Insufficient funds"))

如何创建实例W1

ELISP> (defvar W1 (funcall (withdraw 100)))

withdraw 不是 make-withdraw -- 你调用了别的东西。

ELISP> W1
(lambda ...)

并且 lexical-binding 未定义其他内容处于活动状态,否则您将看到一个闭包。

至于这个...

(make-withdraw 10)
(defvar W1 (make-withdraw 100))
(funcall (W1 30))

您正在为 变量 W1 分配一个函数,这意味着(正如您从此处最近的其他问题中了解到的那样)您 不能 使用 (W1 30) 但必须使用 (funcall W1 30)