[racket] lazy letrec-values

From: Matthias Felleisen (matthias at ccs.neu.edu)
Date: Sun Jul 13 11:44:29 EDT 2014

Both issues are really about the idea that lazy languages 
delay the right-hand side of definitions until the program
has determined what is in demand (and what isn't). 

1. As you point out (define x y) thus imposes a large cost 
on lazy programs. But that's the whole point of laziness. 
It is less expressive than strictness and it is more expensive, 
because everything happens at higher order type levels (not
type in the static sense). 

2. This slogan also explains the 'values' problem. An MV 
communication is a parallel flow of values. When this parallel
flow connects a right-hand side with a left-hand side, its 
individual pieces must be delayed. If not, the delay may or
may not be necessary because the pieces may end up in a strict 
position. So at least in principle the question of whether an 
expression in a value position must be delayed is something to
be computed. 

A classical type system may or may not provide the answer. 
A non-classical one will, by definition of the word 'type'. 

-- Matthias








On Jul 13, 2014, at 4:38 AM, Eli Barzilay wrote:

> On Fri, Jul 11, 2014 at 1:41 AM, Stephen Chang <stchang at ccs.neu.edu> wrote:
>> Actually, this is a bug, because the expression in a single-argument
>> values call is forced prematurely.
> 
> IMO, the whole treatment of multiple values is a hack, for obvious
> reasons.  I was never happy with it, and debated whether the lazy
> language should just drop them completely.  Eventually, I kept them to
> make it more similar to plain racket, and to be able to talk to non-lazy
> code that may use them.
> 
> The issue here is a good example for why it's a hack, with no good
> solution.  IIUC, (I can't actually try it), the patch that was merged
> fixes this:
> 
>> 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
> 
> and makes the former return 1, but now you get a different kind of
> breakage where
> 
>  (let-values ([(x) (values (error "a"))]) 1)
>  (let-values ([(x)         (error "a") ]) 1)
> 
> are not the same.  More than that, the hack of dealing with multiple
> values is at such a (bad) level, that it's possible that the patch would
> break code that assumes that `E' is equivalent to (values E).
> 
> A more proper way to deal with `*-values' constructs would be for the
> macro to treat a case of != 0 values differently from a single value, so
> the force that breaks the above is not done.  That is, this kind of
> change would make these two:
> 
>> (let-values ([(x) (values (error "poof"))]) 1)
>    1 ; `values' doesn't wrap, but (x) means no !-ing
>> (let-values ([(x y) (values (error "poof"))]) 1)
>    poof ; since now there are (x y) so the macro !s the RHS
> 
> This is clearly not great either, but I think that overall it would be
> more consistent.  (But of course it's not a 10-second fix.)
> 
> (A much better way to deal with MVs is to have "TLR" (= TR+LR).)
> 
> -- 
>          ((lambda (x) (x x)) (lambda (x) (x x)))          Eli Barzilay:
>                    http://barzilay.org/                   Maze is Life!
> ____________________
>  Racket Users list:
>  http://lists.racket-lang.org/users


Posted on the users mailing list.