babon
babon

Reputation: 3774

Regarding the "set!" and "let" expressions

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

Answers (3)

molbdnilo
molbdnilo

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

sds
sds

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

hyperlinq
hyperlinq

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

Related Questions