Re: [rust-dev] do we need lambda?

2011-12-05 Thread Niko Matsakis
Ah, I see now that nested functions cannot access upvars.  I was under 
the impression this limitation had been removed.  I did not intend to 
take away access to upvars (as you and Graydon said, crucial to event 
callbacks) but just the anonymous function syntax.


However, I've been thinking it over more since last night and now I 
think that this is not a very good idea.  It'll make the language feel 
heavy and we want it to feel light.  What might be nice, then, is a less 
ponderous syntax than lambda syntax.


In any case, I am still toying with what unique closures ought to be.  
One problem I have uncovered (and it's already a bug today) is that a 
unique closure must be very careful what it does with its unique, 
closed-over state.  The problem is that a unique closure can be invoked 
multiple times.  Not so good if you are moving or dropping unique 
variables.


For example, this code crashes today:

fn foo(-x: ~int) { }
fn main() {
let b = bind foo(~3);
b();
b();
}
The error is that bind needs to "re-copy" the ~3 each time `b()` is 
invoked, but it doesn't. In other words, that bind code is equivalent to 
`let x = ~3 in fn () -> foo(x)` (in some weird O'Caml/Rust hybrid) but 
it would need to be `fn() -> let x = ~3 in foo(x)` to be safe.


This problem can be addressed in many ways and I am not sure what is 
best.  One option is to say that unique closures cannot move or dispose 
of their upvars (here, bind is moving its upvar, essentially).  
Essentially upvars become like a field of a record or other immutable 
location, which must be accessed via swap.  This is safe but somewhat 
disappointing, because most unique closures will be used to spawn a task 
and therefore executed only once.


Another option is to specify that a unique closure can be invoked only 
once (calling it consumes itself).  This is also limiting if that's not 
what you want, but it probably is.  In particular it does not allow 
unique closures to become the foundation for a map/reduce library.


All in all, I am just not sure that unique closures are the right tool 
for a "user-friendly", simple parallelism API, which I understood to be 
one of their goals.  In other words, if you want to fork off a bunch of 
tasks to process the various elements in your array and then pull them 
back in, unique closures don't really give you the guarantees you want.


On the other hand, unique closures do serve a useful purpose for 
spawning off a task and handing it data.  This could also be simulated 
today using a wrapper that creates a channel, starts a new task, passes 
the value over the channel, and finally invokes your function.  Of 
course this adds overhead for something that (may?) be a common case.  
But I am not sure if moving one-off data like that *is* a common case.



Niko

On 12/5/11 8:33 AM, David Rajchenbach-Teller wrote:

On Mon Dec  5 14:27:18 2011, Marijn Haverbeke wrote:

If bind is staying (there was talk of removing it in favour of lambda
at some point), I think we can do without lambda. But the concept of
shared closures (which is what bind creates) would still be there.
___
Rust-dev mailing list
Rust-dev@mozilla.org
https://mail.mozilla.org/listinfo/rust-dev

What would be removed exactly? I strongly believe that we need a form of
closures, e.g. for registering event callback, whether to a GUI, or for
network or system events.

Now, of course, as long as we have some ability to pair a data structure
and a function pointer, and a standard way to represent functions
expecting this kind of data structure, we can always fallback to manual
closure conversion, at the expense of some readability.

I wonder, what exactly would be gained by removing lambdas?

Cheers,
  David



___
Rust-dev mailing list
Rust-dev@mozilla.org
https://mail.mozilla.org/listinfo/rust-dev


Re: [rust-dev] do we need lambda?

2011-12-05 Thread David Rajchenbach-Teller
On Mon Dec  5 14:27:18 2011, Marijn Haverbeke wrote:
> If bind is staying (there was talk of removing it in favour of lambda
> at some point), I think we can do without lambda. But the concept of
> shared closures (which is what bind creates) would still be there.
> ___
> Rust-dev mailing list
> Rust-dev@mozilla.org
> https://mail.mozilla.org/listinfo/rust-dev

What would be removed exactly? I strongly believe that we need a form of
closures, e.g. for registering event callback, whether to a GUI, or for
network or system events.

Now, of course, as long as we have some ability to pair a data structure
and a function pointer, and a standard way to represent functions
expecting this kind of data structure, we can always fallback to manual
closure conversion, at the expense of some readability.

I wonder, what exactly would be gained by removing lambdas?

Cheers,
 David



signature.asc
Description: OpenPGP digital signature
___
Rust-dev mailing list
Rust-dev@mozilla.org
https://mail.mozilla.org/listinfo/rust-dev


Re: [rust-dev] do we need lambda?

2011-12-05 Thread Graydon Hoare

On 05/12/2011 5:27 AM, Marijn Haverbeke wrote:


If bind is staying (there was talk of removing it in favour of lambda
at some point), I think we can do without lambda. But the concept of
shared closures (which is what bind creates) would still be there.


I don't have a strong feeling about it. I initially didn't want *any* 
direct environment capture forms, just bind, but I definitely have a 
higher level of pain tolerance on this issue than most :)


I think blocks seem to be handling most of the "one-off throwaway 
function" uses in our code, most of the time, right now. But we're not 
done exploring the space of code-to-write. Compilers aren't everything.


I think the use-case for shared lambda is registering persistent 
callbacks, such as in a GUI.


I think the use-case for registering unique lambda is spawning tasks. We 
hack around this now but need it eventually.


How awkward would these be without lambda? What do you have in mind for 
the unique closures?


-Graydon
___
Rust-dev mailing list
Rust-dev@mozilla.org
https://mail.mozilla.org/listinfo/rust-dev


Re: [rust-dev] do we need lambda?

2011-12-05 Thread Marijn Haverbeke
If bind is staying (there was talk of removing it in favour of lambda
at some point), I think we can do without lambda. But the concept of
shared closures (which is what bind creates) would still be there.
___
Rust-dev mailing list
Rust-dev@mozilla.org
https://mail.mozilla.org/listinfo/rust-dev


[rust-dev] do we need lambda?

2011-12-04 Thread Niko Matsakis

Hello,

I wanted to do a quick straw poll to ask whether we still need a lambda 
expression, given that we have blocks and named functions?  Searching 
the rust code base, I found that *every* use of lambda was of the form: 
|let foo = lambda(...) {...}| which would (in my opinion) be better 
written: |fn foo(...) {...}|.


I am not asking because I like stripping out unused expression forms, 
though I do, but rather because I am thinking about the precise design 
for unique closures (separate e-mail coming soon) and the fewer ways to 
declare closures the simpler the job becomes.



Niko
___
Rust-dev mailing list
Rust-dev@mozilla.org
https://mail.mozilla.org/listinfo/rust-dev