Hi,
I'm new to Scheme, and new to Gambit, so I apologize if my question is silly.
I think that the concept of wrapping a (let …) around a (lambda …) is really neat, which got me wondering about what happens if you create a circular reference to a lambda from the scope of the let that surrounds it… in particular, should such a circular reference get garbage collected? (And if so, WOW, that's a pretty clever garbage collector!)
In the following program I create 3 objects ("one", "two", and "three"), and create wills for them. Then I destroy my references to all three objects and call the garbage collector. The result is that 2 of the 3 objects gets garbage collected.
My question is, is this the expected behaviour, or have I stumbled across something more sinister?
Here's the code:
- - - CODE STARTS HERE - - -
(define (circ-obj name) (let* ((data '(a . b) ) (func (lambda () (println "executing func for object "" name "" proc: " data)))) (set-car! data func) ; (set-cdr! data fund) ; (set! data func) func))
(define one (circ-obj 'one)) (println "CREATING ONE") (pp one) (one)
(println)
(define two (circ-obj 'two)) (println "CREATING TWO") (pp two) (two)
(println)
(define three (circ-obj 'three)) (println "CREATING THREE") (pp three) (three)
(println)
(println "CREATING WILLS") (define wone (make-will one (lambda (obj) (println "killing one " obj)))) (define wtwo (make-will two (lambda (obj) (println "killing two " obj)))) (define wthree (make-will three (lambda (obj) (println "killing three " obj))))
(println)
(println "DESTROYING ONE") (set! one #f) (##gc)
(println)
(println "DESTROYING TWO") (set! two #f) (##gc)
(println)
(println "DESTROYING THREE") (set! three #f) (##gc)
(println)
(println "Done!")
- - - CODE ENDS HERE - - -
When I run this I get the following result:
- - - SAMPLE RUN STARTS HERE - - -
CREATING ONE (lambda () (println "executing func for object "" name "" proc: " data)) executing func for object "one" proc: #<procedure #2 one>b
CREATING TWO (lambda () (println "executing func for object "" name "" proc: " data)) executing func for object "two" proc: #<procedure #3 two>b
CREATING THREE (lambda () (println "executing func for object "" name "" proc: " data)) executing func for object "three" proc: #<procedure #4 three>b
CREATING WILLS
DESTROYING ONE killing one #<procedure #2>
DESTROYING TWO killing two #<procedure #3>
DESTROYING THREE
Done!
- - - SAMPLE RUN ENDS HERE - - -
Notice that the will for object "three" never gets called, which I think means that the object hasn't been recollected by the garbage collector.
Anyway, all I'm really hoping for is an indication as to whether such circularly referenced objects should or should not be garbage collected.
Thanks!