[racket] lazy letrec-values

From: Spencer Florence (florence at northwestern.edu)
Date: Fri Jul 11 00:02:23 EDT 2014

It looks like he has taken those down. But I'm sure he would email a copy
if asked (the think is http://pl.barzilay.org/resources.html#classnotes btw)


On Thu, Jul 10, 2014 at 8:42 PM, Matthias Felleisen <matthias at ccs.neu.edu>
wrote:

>
> There are also Eli's class notes. I don't have a URL handy but I am sure
> if you google "Eli Barzilay" and "course" you'll find his notes on the
> various levels of lazy (plus homework assignments :-) -- Matthias
>
>
>
>
>
>
> On Jul 10, 2014, at 6:41 PM, Stephen Chang wrote:
>
> > Actually, this is a bug, because the expression in a single-argument
> > values call is forced prematurely.
> >
> > eg, This should not error:
> >
> > -> (let-values ([(x) (values (error "a"))]) 1)
> > ; a [,bt for context]
> >
> > Just like this does not error.
> >
> > -> (let-values ([(x y) (values (error "a") (error "b"))]) 1)
> > 1
> >
> > Lazy Racket is trying to preserve the (values x) == x from Racket, but
> > since LR's force is recursive, this is actually impossible without
> > breaking the semantics like it's doing now.
> >
> > Luke, thanks for finding this. If you want to submit a pull request, I
> > will merge. (Just drop the first clause in the case-lambda entirely.)
> > Maybe some extra tests would be nice as well :) Otherwise if you dont
> > have time, let me know and I'll do it.
> >
> >> 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 ?
> >
> > There isnt any. You can check out the Barzilay-Clements paper [1] to
> > learn about the motivation behind LR, but otherwise LR should have
> > "standard" lazy semantics.
> >
> > [1]:
> http://digitalcommons.calpoly.edu/cgi/viewcontent.cgi?article=1047&context=csse_fac
> >
> > On Thu, Jul 10, 2014 at 1:15 PM, Luke Whittlesey
> > <luke.whittlesey at gmail.com> wrote:
> >> 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
> >>
> >>
> >>
> >> ____________________
> >>  Racket Users list:
> >>  http://lists.racket-lang.org/users
> >>
> > ____________________
> >  Racket Users list:
> >  http://lists.racket-lang.org/users
>
>
> ____________________
>   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/289b1471/attachment.html>

Posted on the users mailing list.