A couple of questions regarding let, hoisting and block scope

Claus Reinke claus.reinke at talk21.com
Mon Mar 21 09:13:09 PDT 2011

I was looking forward to a Javascript with block scope at last,
but on looking through the proposals, I have some questions:

1. hoisting vs recursive function definitions

    Hoisting isn't nice in general, and from the "no use before 
    declaration" in [1], it seems that let bindings won't be hoisted,
    not even to their enclosing block.

    But hoisting is also the basis for making mutually recursive
    function definitions work without pain. Will we have to 
    declare all function names of recursive function groups 
    ahead of defining them (with a top-down parser, there'd
    be many more than just two function names to list)? 

    let odd, even; // needed?
    odd = function (n) { .. even(n-1) ..}
    even = function (n) { .. odd(n-1) ..}

    or, with #functions [2]

    const odd, even; // needed?
    const #odd (n) { .. even(n-1) ..}
    const #even (n) { .. odd(n-1) ..}

    Once function definitions are constant, there doesn't seem
    to be much harm in a limited form of hoisting: for a sequence
    of constant function definitions, not interrupted by other 
    statements, implicitly introduce all function names defined 
    in the sequence at the start of the sequence (to simplify 
    recursive definitions).

    The alternatives would be manual duplication of function 
    name lists, or introducing a dedicated letrec syntax for 
    recursive definitions (the latter might actually be preferable).

    Am I missing something here, or hasn't this been discussed?
2. ease of transition

    The general idea seems to be to introduce separate syntax,
    to force programmers to "buy in" to the new semantics. This
    should lead to a clean transition, but not an easy one.

    The downside is that no-one can test the waters as long as 
    old implementations (do not understand 'let') retain substantial 
    marketshare. This is sad because implementations could
    start helping programmers right now (read: from the next
    release), to prepare for the eventual transition.

    One idea would be to start separating "strong" and "weak"
    blocks, where weak blocks '{ }' are the standard, non-scoped
    ones and strong blocks '{{ }}' (to steal no syntax) would be
    block-scoped (for instance, map to "(function() { }())" ).

    [we can't map '{{ }}' by translating 'var' to 'let': unless all
     blocks involved are strong blocks, 'let' is more local]

    Another idea would be to add a pragma: "no hoisting";
    (or extend "use strict" to encompass this). Upon which
    the implementation should warn or error on any code
    that captures variable occurences by hoisting. For instance:

    function F() {
        "no hoisting";
        .. x ..
        if ( .. ) { var x; .. }
        .. x ..

    should produce warnings (at least at the hoisted declaration,
    probably also at the captured uses).    


[1] http://wiki.ecmascript.org/doku.php?id=harmony:let
[2] http://brendaneich.com/2011/01/harmony-of-my-dreams/

More information about the es-discuss mailing list