I just sent a pull request : https://github.com/plt/racket/pull/727
I added a few simple test cases, but the interesting thing is that running `./racket/bin/raco test pkgs/lazy` seems to pass even when I add a failing test case such as `(! (eq? 1 2)) => #t`. That same test will fail as expected if I run it within drracket. Thank you all for your time and help. (And thank you for creating such a nice community and toolset!) -Luke On Fri, Jul 11, 2014 at 12:02 AM, Spencer Florence < flore...@northwestern.edu> wrote: > 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 <matth...@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.whittle...@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 <mfl...@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 >> > > > ____________________ > Racket Users list: > http://lists.racket-lang.org/users > >
____________________ Racket Users list: http://lists.racket-lang.org/users