I think the situation is somewhat more complex than you suggest.
First, heap-based closures like fn@ and fn~ copy values from the
environment at the point of creation. This is particularly relevant for
mutable variables. To allow for mutual recursion, we would need some
sort of expression form that allows multiple functions to be declared
simultaneously. This is not a bad idea, but nobody has proposed nor
implemented a specific construct in this direction. In any case it is
quite different from a nested bare fn, because there is a specific point
of initialization vs bare functions that are always valid.
For stack closures (i.e., closures that access the surrounding
environment 'by reference', rather than copying values out), that issue
is not relevant, but there are other issues. Essentially we must
consider any free variables that are referenced by a stack closure to be
"borrowed" for the duration of the closure. So it is important that we
identify the point where the closure is created and the scope of the
closure. What we don't want is something like this:
fn foo() {
let x = 10;
// at point of creation, x is initialized
let y = &fn() { ... use x ... };
send(x); // x is deinitialized
y(); // references x, bad!
}
Of course, as the previous example suggests, we have to do this anyway
once we generalize stack closures a bit so that they can be stored in
variables and heap structures.
So basically both issues are the same: if/when we permit named, mutually
recursive closures, we will need to be careful about designating the
point of creation for the closure and (in the case of stack closures)
its lifetime.
Niko
On 7/13/12 1:14 PM, David Bruant wrote:
Le 13/07/2012 21:42, Patrick Walton a écrit :
On 7/13/12 12:38 PM, David Bruant wrote:
I can't help but asking why can't named function close over their
environment?
In the case above, I see no harm in allowing the 'bar' function to
access 'foo'.
Because named functions are always in scope (they're always mutually
recursive), while locals are not. For example, these two are equivalent:
fn f() {
g();
fn g() { ... }
}
fn f() {
fn g() { ... }
g();
}
But if we allowed items to close over variables, then that wouldn't be
the case anymore. This cannot be allowed:
fn f() {
g();
let x = ...;
fn g() { ... use x ... }
}
Because x has not yet been initialized.
Tell me if I'm wrong, but it seems that a use-before-init can be
detected statically at compile time. It wouldn't be the case for
JavaScript, but I think it's feasible in Rust.
Unless I'm missing something, named function could close over variables
and the compiler could throw an error when a named function is being
used in a use-before-init scenario.
David
_______________________________________________
Rust-dev mailing list
[email protected]
https://mail.mozilla.org/listinfo/rust-dev
_______________________________________________
Rust-dev mailing list
[email protected]
https://mail.mozilla.org/listinfo/rust-dev