Mark S. Miller wrote:
> On Sat, Oct 11, 2008 at 8:35 PM, David-Sarah Hopwood
> <david.hopwood at industrial-designers.co.uk> wrote:
>> The reason for making 'const' hoist to the top of the enclosing block,
>> AFAIR, was consistency with function declarations. However, there are
>> good reasons why 'const'/'let' and function declarations should be
>> treated differently:
>> The following issue invalidates one of your reasons.
>> {
> .... f(); ...
>> const x = 3;
>> function f() { ... x ... }
> }
Why does this need to be allowed? This example will *always* fail whenever
f() actually accesses x. A static error is perfectly reasonable.
It is possible that f() might not access x in the particular call(s) to
it that run before 'x = 3', but in that case the declaration of x should
be manually hoisted above the call to f:
{
let x; // equivalent to let x = undefined;
... f(); ...
x = 3;
function f() { ... x ... }
}
which makes it clear that f() can refer to x, that x is actually mutable
(because both 'x === undefined' and 'x === 3' are observable states),
and that x = 3 is an assignment, not an initializer.
> Since functions hoist, if const do not, then in the example above, either
> 1) we must not allow f to refer to x, or
> 2) we must still have a read barrier, since f may still be invoked and
> access x before x is initialized.
3) we allow f to refer to x, but disallow the reference to f outside the
scope of x.
More generally,
- if a function refers to a 'let' or 'const' variable, its effective
scope is intersected with the scope of that variable.
This rule is simple, easy to explain and motivate, does not
unnecessarily reject "good" programs, and is straightforward to work
around in cases where the program would be dynamically safe.
If it is used then no read or write barriers are required.
--
David-Sarah Hopwood