Well, it compiles, but you’d be surprised maybe how something like that runs
(
value {
var bar = 4;
value {
var bar = bar + 1;
bar.postln;
}
}
)
ERROR: Message '+' not understood. RECEIVER: nil
The initializer expression doesn’t actually access the outer scope once bar has beed var
’d. This could arguably even be considered a bug (even) in the present compiler implementation.
In theory, there’s no strong reason why the initializer expressions aren’t a bit smarter about scope (i.e. exclude the var just being declared from inner-scope lookup), but I guess nobody cared about this corner case, so the simplest implementation (just immediately create the lookup entry in the inner scope) for bar is what’s done, before the initializer expression is considered / evaluated.
As far as the proposed new semantics goes, in theory it would be ok with this kind of expression, even if it were to access the outer scope in the initializer (which presently doesn’t happen), because the = bar
initializer expression comes after the re-declaration. When the inner var bar
is reached, the outer bar
was not accessed in the inner scope yet, so the bar
name is clear/clean to be var’d in the inner scope. (arg
doesn’t seem any different in that respect.)
Only something like
{
var bar = 5;
{
bar = bar + 1; // ok, outer scope access
var bar = bar; // compile error would be raised here ...
}
}
… because the bar
name is already accessed before this point in the inner scope. But the latter does not parse in SC presently anyway.
Somewhat surprisingly, the following is “borked” too in the present compiler, when it comes to running
(
value {
var bar = 4;
value {
var tmp = bar + 1, bar = tmp;
tmp.postln;
}
}
)
It works ok without the bar = tmp
part. Basically, in the present compiler the whole list of var
s is created “in one pass”, then all the initializers are considered / evaluated. So tacking that bar = tmp
screws up the lookup of the bar + 1
initializer, even if the latter appears to “come before” the (re)declaration of bar.
Basically that compiles as if it were written like
(
value {
var bar = 4;
value {
var tmp, bar;
tmp = bar + 1;
bar = tmp;
tmp.postln;
}
}
)
I.e. there’s “hoisting lite” done on (all) the var declarations themselves before the initializers.