I am reading the example 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
Practice with 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
Did not work as expected, experiment it interactively
Case 1: call make-withdraw
directly and return a closure
;; lexical-binding t
ELISP> (make-withdraw 100)
(closure
((balance . 100)
t)
(amount)
(if
(>= balance amount)
(progn
(setq balance
(- balance amount))
balance)
"Insufficient funds"))
Case 2: Assign it to a W1, yet return a common function rather than a closure
ELISP> (defvar W1 (funcall (withdraw 100)))
W1
ELISP> W1
(lambda
(amount)
(if
(>= balance amount)
(progn
(setq balance
(- balance amount))
balance)
"Insufficient funds"))
How could create an instance W1
?
ELISP> (defvar W1 (funcall (withdraw 100)))
withdraw
is not make-withdraw
-- you've called something else.
ELISP> W1
(lambda ...)
And that something else was not defined with lexical-binding
active, otherwise you would be seeing a closure.
As for this...
(make-withdraw 10)
(defvar W1 (make-withdraw 100))
(funcall (W1 30))
You're assigning a function to a variable W1
which means (as you know from your other recent questions here) that you cannot use (W1 30)
but would instead have to use (funcall W1 30)