[racket] lazy letrec-values

From: Luke Whittlesey (luke.whittlesey at gmail.com)
Date: Thu Jul 10 13:15:49 EDT 2014

Thank you for the in-depth analysis. Very interesting.

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.)

at lazy.rkt line:223
replace:
  (define* ~values
    (case-lambda [(x) x] [xs (multiple-values xs)]))

with:
  (define* ~values
    (case-lambda [(x) (multiple-values (list x))] [xs (multiple-values
xs)]))


I had assumed that a reference to an identifier was delayed, so thanks for
showing that this is currently not the case.

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 ?

Thanks,
Luke


On Thu, Jul 10, 2014 at 6:24 AM, Matthew Flatt <mflatt at cs.utah.edu> wrote:

> I'm not sure whether to call it a bug or a limitation of `lazy`.
>
> The `lazy` language doesn't delay a reference to an identifier. As a
> result,
>
>  (define x y)
>  (define y (list 1))
>  (car x)
>
> fails. The case could be made that the right-hand side of the definition
> of `x` should have been a lazy reference to `y`, but that's not what
> `lazy` currently does.
>
> A problem with the current choice is that it interacts badly with `!`,
> especially as used by `letrec-values`. The implementation of
> `letrec-values` forces the right-hand side of a binding using `!` to
> determine how many values it produces. That works ok when the
> right-hand side is produced by `values` on more than one argument,
> because `values` produces a special multiple-values result that leaves
> its values unforced after `!`. When `values` get one argument, then it
> just returns the argument.... and that's still ok for something like
> `(values (list 1 (/ 0)))`, because the `(/ 0)` expression is lazy.
>
> In your example, the implicit use of `!` for the right-hand side of the
> A` binding produces `(! (list a B))`. That `B` is not itself treated as
> a lazy expression, so forcing the list to be constructed causes `B` to
> be evaluated early.
>
> You can make the variable reference lazy by wrapping it with `~`:
>
>   (letrec-values ([(A) (values (list 'a (~ B)))]
>                   [(B) (values (list 'b A))])
>     B)
>
> Again, I don't know that you should have to do that, but it's how
> `lazy` is defined at the moment.
>
> At Mon, 7 Jul 2014 15:06:26 -0400, Luke Whittlesey wrote:
> > Hello all,
> > I've been playing around with creating circular lists (and learning
> racket
> > which has been quite fun), but I'm stumped on why the lazy version of
> > letrec-values is not producing a promise like the lazy version of letrec
> > does. With the lazy letrec I can create circular lists, but with the lazy
> > letrec-values I get #<undefined>. See the example below.
> >
> > ;;;;;;;;;;;;;;;;; example code ;;;;;;;;;;;;;;;;;;;;;;;;;
> > #lang lazy
> >
> > ;; create a circular list using letrec (this works)
> > (define example-working
> >   (letrec ([A (list 'a B)]
> >            [B (list 'b A)])
> >     B))
> > (displayln "Working Example:")
> > (displayln example-working)
> > (displayln (!! example-working))
> >
> > ; Prints...
> > ;Working Example:
> > ;(b #<promise:A>)
> > ;#0=(b (a #0#))
> >
> > ;; create a circular list using letrec-values (this is broken)
> > (define example-broken
> >   (letrec-values ([(A) (values (list 'a B))]
> >                   [(B) (values (list 'b A))])
> >     B))
> > (displayln "Broken Example:")
> > (displayln example-broken)
> > (displayln (!! example-broken))
> >
> > ; Prints
> > ;Broken Example:
> > ;(b (a #<undefined>))
> > ;(b (a #<undefined>))
> > ;;;;;;;;;;;;;;;;; end code ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
> >
> > I realize that there are many different ways to generate circular lists,
> > but why doesn't this work? Am I misunderstanding something or is this a
> bug?
> >
> > Thanks,
> > Luke
> > ____________________
> >   Racket Users list:
> >   http://lists.racket-lang.org/users
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.racket-lang.org/users/archive/attachments/20140710/c1cce74d/attachment.html>

Posted on the users mailing list.