<div>Dear Marc,</div><div><br></div><div><div>How can I make Gambit always generate unique closure objects for (lambda () ...) ?</div></div><div><br></div><div>A (declare) to enforce this would do the job.</div><div><br></div>

<div><br></div><div>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.</div><div><br></div><div>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.</div>

<div><br></div><div>This was quite surprising to me as my best understanding of R5RS spec (<a href="http://schemers.org/Documents/Standards/R5RS/HTML/r5rs-Z-H-9.html#%_sec_6.1">here</a> & <a href="http://schemers.org/Documents/Standards/R5RS/HTML/r5rs-Z-H-7.html#%_sec_4.1.4">here</a>) is that eq? should work on procedures:</div>

<div><blockquote style="margin:0 0 0 40px;border:none;padding:0px"><div><br></div><div><span style="background-color:rgb(255,255,255)"><font face="arial, helvetica, sans-serif">"Each procedure created as the result of evaluating a <tt>lambda</tt> expression is (conceptually) tagged with a storage location, in order to make <tt>eqv?</tt> and <tt>eq?</tt> work on procedures (see section <a href="http://schemers.org/Documents/Standards/R5RS/HTML/r5rs-Z-H-9.html#%_sec_6.1">6.1</a>)."</font></span></div>

</blockquote></div><div><br></div><div>Perhaps the wording could have been even more precise.</div><div><br></div><div><br></div><div>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.</div>

<div><br></div><div>Thanks!</div><div>Mikael</div><div><br></div><div><br></div><div>Example:</div><div><div><br></div><blockquote style="margin:0px 0px 0px 40px;border:none;padding:0px"><div><font face="courier new, monospace">$ <b>gsc</b></font></div>

<div><div><div><font face="courier new, monospace">Gambit v4.6.6</font></div><div><font face="courier new, monospace"><br></font></div></div><div><font face="courier new, monospace">> <b>(let loop () (define x (lambda () 'myvalue)) (print x "\n") (loop))</b></font></div>

</div><div><font face="courier new, monospace">#<procedure #2 x></font></div><div><font face="courier new, monospace">#<procedure #3 x></font></div><div><font face="courier new, monospace">#<procedure #4 x></font></div>

<div><font face="courier new, monospace">#<procedure #5 x></font></div><div><font face="courier new, monospace">[...]</font></div><div><b><font face="courier new, monospace">[ctrl+c],q</font></b></div><div><b><font face="courier new, monospace"><br>

</font></b></div><div><div><font face="courier new, monospace">$ <b>echo </b><b>(let loop () (define x (lambda () 'myvalue)) (print x "\n") (loop)) > test.scm</b></font></div></div><div><font face="courier new, monospace">$ <b>gsc</b></font></div>

<div><div><font face="courier new, monospace">Gambit v4.6.6</font></div><div><font face="courier new, monospace"><br></font></div></div><div><font face="courier new, monospace">> <b>(compile-file "test.scm")</b></font></div>

<div><font face="courier new, monospace">"test.o1"</font></div><div><font face="courier new, monospace">> <b>(load "test.o1")</b></font></div><div><div><font face="courier new, monospace">#<procedure #2></font></div>

<div><font face="courier new, monospace">#<procedure #2></font></div><div><font face="courier new, monospace">#<procedure #2></font></div><div><font face="courier new, monospace">#<procedure #2></font></div>

<div><font face="courier new, monospace">#<procedure #2></font></div><div><font face="courier new, monospace">#<procedure #2></font></div><div><font face="courier new, monospace">#<procedure #2></font></div>

</div><div><font face="courier new, monospace">[...]</font></div><div><font face="courier new, monospace"><br></font></div></blockquote></div><div>This</div><blockquote style="margin:0px 0px 0px 40px;border:none;padding:0px">

<font face="courier new, monospace"><br>(let loop ((v 0)) (define x (lambda () <b>v</b> 'myvalue)) (print x "\n") (loop 1))</font></blockquote><div><font face="arial, helvetica, sans-serif"><br></font></div>

<div><font face="arial, helvetica, sans-serif">gives the same behavior. Note that the lambda closes over v, though the compiler optimizes it away.</font></div><div><font face="courier new, monospace"><br></font></div><div>

Neither </div><div><br></div><blockquote style="margin:0 0 0 40px;border:none;padding:0px"><div><div><font face="courier new, monospace">(let loop ((v 0)) (define x (lambda (z) (declare (not optimize-dead-local-variables)) v 'myvalue)) (print x "\n") (loop 1))</font></div>

</div></blockquote><div><br></div><div>works, which may appear a bit surprising!</div><div><br></div><div><br></div><div>Here's a hack around the optimizer though:</div><div><br></div><div><blockquote style="margin:0 0 0 40px;border:none;padding:0px">

<div><div><font face="courier new, monospace">(let loop ((v 0)) (define x (lambda (z) (case z ((never-happens) v) (else 'myvalue)))) (print x "\n") (loop 1))</font></div></div><div><br></div></blockquote></div>

<div><br></div>