Reputation: 3774
I have got this small program defined in a file a.scm
:
(define f
(let ((x 0))
(lambda ()
(set! x (+ 1 x))
x)))
Upon calling f
repeatedly, the result keeps on increasing:
CHICKEN
(c) 2008-2016, The CHICKEN Team
(c) 2000-2007, Felix L. Winkelmann
Version 4.11.0
linux-unix-gnu-x86-64 [ 64bit manyargs dload ptables ]
compiled 2016-08-23 on buildvm-13.phx2.fedoraproject.org
#;1> (load "a.scm")
; loading a.scm ...
#;2> (f)
1
#;3> (f)
2
#;4> (f)
3
#;5>
Could someone please throw some light as to why x
is bound to 0
only the first time f
is invoked? I expect that every time f
is invoked, the let
binding should get executed.
Also, if on repeated invocations, x
is not bound to 0
then how does the lambda expression get to know that x
is a 'free variable' within it's body (instead of returning an error like 'variable not bound` or something)?
Thanks.
Upvotes: 0
Views: 82
Reputation: 66371
The let
is not inside the function's body; the let
is evaluated when f
is defined, not when it's called.
The function's body is (set! x (+ 1 x)) x)
, where x
refers to the variable defined by the let
.
Or to put another way, f
is not bound to the let
but to the lambda
.
Similarly,
(define x (let ((y 12)) y))
binds x
to 12
, not to (let ((y 12)) y)
.
Upvotes: 1
Reputation: 60014
Could someone please throw some light as to why x is bound to 0 only the first time f is invoked?
x
is bound to 0 not when f
is invoked, but when it is created.
Let me rewrite your function in Common Lisp:
(let ((x 0))
(defun f ()
(incf x)))
(f)
==> 1
(f)
==> 2
(f)
==> 3
(f)
==> 4
f
is a closure over the variable x
.
IOW, when f
is created, x
is bound to 0 and made available in f
- and only in f
.
Upvotes: 2
Reputation: 31
I understood set!
as 'binding a value to a symbol directly in the constant environment', which means that the symbol (here x
) isn't available to bindings (such as let or a function parameter) anymore.
The only procedure that can override this 'binding to a symbol' is another set!
. So, when you call your function over and over again, it looks up the symbol x
and does a new 'set!'. If you reload your file new, this binding should be reset. Does it?
btw...did someone say CHICKEN ?
Upvotes: 0