Hi, I just found myself writing a recursive closure, but I get an
error if I try to refer to the variable which contains the closure
from within the closure.
I don't think so. I saw a check-in recently, maybe to Frog, that fixed
a bug like this. Are you running with Frog, dartc, or the VM?
-Justin
>
> Cheers,
> Chris.
var myFunc = () {
if (foo) {
myFunc();
}
else {
//recurse back out
}
};
create closure X with body () {
if (foo) {
// What is my funct? it does not exists nowhere yet
myFunc();
}
else {
//recurse back out
}
};
create variable myFunc
assing closure X to myFunc
var funct = function() {
funct();
}
create variable funct;
create closure X with body function() {
// funct exists but it is null, now I know which variable I'm referencing
funct();
}
assing closure X to funct;
myFunc() {
myFunct();
}
create closure myFunct with body () {
// Ok, I know you are referencing myself
myFunct();
}
So what you are saying is that in the example:
main() {
var myFunc = (foo) {
if (foo > 0) {
myFunc(foo - 1);
}
else {
//recurse back out
}
};
myFunc(5);
}
the compiler cannot tell that myFunc has been declared,
var a = b + c;
var a = a;print(a);
and thus cannot dynamically invoke the closure that (eventually) is contained
in myFunc. That smells like a bug.
I would assume that there would be a sort of lazy evaluation of the variable myFunc(foo - 1); line.
Does the call site need to be bound at compile time?
var a = a;print(a);
It's not lazy evaluation, but, yes, most language have special support to allow recursive calls. In JavaScript, this is "hoisting". In C it's forward declarations. Dart has something similar for function declarations, but not for function expressions. So this works:main() {countdown(i) {print(i);if (i > 0) countdown(i - 1);}countdown(10);}But this does not:main() {var countdown = (i) {print(i);if (i > 0) countdown(i - 1);}countdown(10);}
- bob
In Java,
the typechecker inserts the declared variable in the scope but
a later pass the one that verifies that all variables are initialized
before being used
reports an error.
Also the current lambda prototype (for Java 8) has currently a special rule
to allow to use the current lambda inside of itself so variable are
declared as 'let'
in case of classical variable and 'letrec' if it's a lambda.
From the implementation side (this is Java specific), you may have
an unsafe publication of the lambda when creating it
(another thread can see the lambda not fully initialized :( )
so the creation of a recursive lambda requires a memory barrier.
Given that, I'm not sure this rule will be still be there when Java 8
will be released.
>
> - bob
>
cheers,
R�mi