<div dir="ltr"><div><div><div><div><div><div>Thank you for the in-depth analysis. Very interesting. <br><br></div>Following
your reasoning, if I edit lazy.rkt and force `values` to use
`multiple-values` for the single entry case, the example that was
previously broken now works. (I just have no idea if this breaks
something else in the process.)<br><br></div>at lazy.rkt line:223 <br></div>replace:<br> (define* ~values<br> (case-lambda [(x) x] [xs (multiple-values xs)]))<br><br></div>with:<br> (define* ~values<br> (case-lambda [(x) (multiple-values (list x))] [xs (multiple-values xs)]))<br>
<br><br></div>I had assumed that a reference to an identifier was delayed, so thanks for showing that this is currently not the case. <br><br></div><div>Beyond the library documentation, does anyone know if there are any discussions or tutorials that go into the do's and don'ts of using #lang lazy ?<br>
</div><div><br></div><div>Thanks,<br>Luke<br></div></div><div class="gmail_extra"><br><br><div class="gmail_quote">On Thu, Jul 10, 2014 at 6:24 AM, Matthew Flatt <span dir="ltr"><<a href="mailto:mflatt@cs.utah.edu" target="_blank">mflatt@cs.utah.edu</a>></span> wrote:<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">I'm not sure whether to call it a bug or a limitation of `lazy`.<br>
<br>
The `lazy` language doesn't delay a reference to an identifier. As a<br>
result,<br>
<br>
(define x y)<br>
(define y (list 1))<br>
(car x)<br>
<br>
fails. The case could be made that the right-hand side of the definition<br>
of `x` should have been a lazy reference to `y`, but that's not what<br>
`lazy` currently does.<br>
<br>
A problem with the current choice is that it interacts badly with `!`,<br>
especially as used by `letrec-values`. The implementation of<br>
`letrec-values` forces the right-hand side of a binding using `!` to<br>
determine how many values it produces. That works ok when the<br>
right-hand side is produced by `values` on more than one argument,<br>
because `values` produces a special multiple-values result that leaves<br>
its values unforced after `!`. When `values` get one argument, then it<br>
just returns the argument.... and that's still ok for something like<br>
`(values (list 1 (/ 0)))`, because the `(/ 0)` expression is lazy.<br>
<br>
In your example, the implicit use of `!` for the right-hand side of the<br>
A` binding produces `(! (list a B))`. That `B` is not itself treated as<br>
a lazy expression, so forcing the list to be constructed causes `B` to<br>
be evaluated early.<br>
<br>
You can make the variable reference lazy by wrapping it with `~`:<br>
<br>
(letrec-values ([(A) (values (list 'a (~ B)))]<br>
<div class=""> [(B) (values (list 'b A))])<br>
B)<br>
<br>
</div>Again, I don't know that you should have to do that, but it's how<br>
`lazy` is defined at the moment.<br>
<div><div class="h5"><br>
At Mon, 7 Jul 2014 15:06:26 -0400, Luke Whittlesey wrote:<br>
> Hello all,<br>
> I've been playing around with creating circular lists (and learning racket<br>
> which has been quite fun), but I'm stumped on why the lazy version of<br>
> letrec-values is not producing a promise like the lazy version of letrec<br>
> does. With the lazy letrec I can create circular lists, but with the lazy<br>
> letrec-values I get #<undefined>. See the example below.<br>
><br>
> ;;;;;;;;;;;;;;;;; example code ;;;;;;;;;;;;;;;;;;;;;;;;;<br>
> #lang lazy<br>
><br>
> ;; create a circular list using letrec (this works)<br>
> (define example-working<br>
> (letrec ([A (list 'a B)]<br>
> [B (list 'b A)])<br>
> B))<br>
> (displayln "Working Example:")<br>
> (displayln example-working)<br>
> (displayln (!! example-working))<br>
><br>
> ; Prints...<br>
> ;Working Example:<br>
> ;(b #<promise:A>)<br>
> ;#0=(b (a #0#))<br>
><br>
> ;; create a circular list using letrec-values (this is broken)<br>
> (define example-broken<br>
> (letrec-values ([(A) (values (list 'a B))]<br>
> [(B) (values (list 'b A))])<br>
> B))<br>
> (displayln "Broken Example:")<br>
> (displayln example-broken)<br>
> (displayln (!! example-broken))<br>
><br>
> ; Prints<br>
> ;Broken Example:<br>
> ;(b (a #<undefined>))<br>
> ;(b (a #<undefined>))<br>
> ;;;;;;;;;;;;;;;;; end code ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;<br>
><br>
> I realize that there are many different ways to generate circular lists,<br>
> but why doesn't this work? Am I misunderstanding something or is this a bug?<br>
><br>
> Thanks,<br>
> Luke<br>
</div></div>> ____________________<br>
> Racket Users list:<br>
> <a href="http://lists.racket-lang.org/users" target="_blank">http://lists.racket-lang.org/users</a><br>
</blockquote></div><br></div>