[gambit-list] What's the best practice for forcing (lambda () ..) to generate a unique closure object always?

Mikael mikael.rcv at gmail.com
Sat Jun 15 20:53:22 EDT 2013


Dear Marc,

How can I make Gambit always generate unique closure objects for (lambda ()
...) ?

A (declare) to enforce this would do the job.


I'm having a table with test: eq? where the key is a closure and thus needs
to guaranteedly be unique. This should be a perfectly valid usecase.

I noted that currently in compiled code (lambda () ...) not guaranteedly
returns a unique closure object in certain circumstances: if a closure
closes over no variables, or Gambit optimizes away all closed over
variables so no variables are closed over that way, then it does not
generate a unique closure.

This was quite surprising to me as my best understanding of R5RS spec (here&
here) is that eq? should work on procedures:


"Each procedure created as the result of evaluating a lambda expression is
(conceptually) tagged with a storage location, in order to make eqv?
and eq? work
on procedures (see section 6.1)."


Perhaps the wording could have been even more precise.


I acknowledge this Gambit optimization is really useful many times. Though
there should be a way to disable it as it wouldn't be a reliable coding
strategy to need to outsmart the optimizer for correct function.

Thanks!
Mikael


Example:

$ *gsc*
Gambit v4.6.6

> *(let loop () (define x (lambda () 'myvalue)) (print x "\n") (loop))*
#<procedure #2 x>
#<procedure #3 x>
#<procedure #4 x>
#<procedure #5 x>
[...]
*[ctrl+c],q*
*
*
$ *echo **(let loop () (define x (lambda () 'myvalue)) (print x "\n")
(loop)) > test.scm*
$ *gsc*
Gambit v4.6.6

> *(compile-file "test.scm")*
"test.o1"
> *(load "test.o1")*
#<procedure #2>
#<procedure #2>
#<procedure #2>
#<procedure #2>
#<procedure #2>
#<procedure #2>
#<procedure #2>
[...]

This


(let loop ((v 0)) (define x (lambda () *v* 'myvalue)) (print x "\n") (loop
1))


gives the same behavior. Note that the lambda closes over v, though the
compiler optimizes it away.

Neither

(let loop ((v 0)) (define x (lambda (z) (declare (not
optimize-dead-local-variables)) v 'myvalue)) (print x "\n") (loop 1))


works, which may appear a bit surprising!


Here's a hack around the optimizer though:

(let loop ((v 0)) (define x (lambda (z) (case z ((never-happens) v) (else
'myvalue)))) (print x "\n") (loop 1))
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mailman.iro.umontreal.ca/pipermail/gambit-list/attachments/20130616/5d634978/attachment.htm>


More information about the Gambit-list mailing list