On dropping @names

Andreas Rossberg rossberg at google.com
Thu Dec 27 14:38:32 PST 2012

On 27 December 2012 21:23, David Herman <dherman at mozilla.com> wrote:

> On Dec 27, 2012, at 1:51 AM, Andreas Rossberg <rossberg at google.com> wrote:
> > I think hoisting can mean different things, which kind of makes this
> debate a bit confused.
> Yep. Sometimes people mean "the scope extends to a region before the
> syntactic position where the declaration appears," sometimes they mean "the
> scope extends to the function body," and sometimes they mean "function
> declaration bindings are dynamically initialized before the containing
> function body or script begins executing."

Maybe we shouldn't speak of hoisting for anything else but the var case. As
I mentioned elsewhere, I rather like to think of it recursive (i.e.
letrec-style) block scoping. :)

> > There is var-style hoisting. Contrary to what Rick said, I don't think
> anybody can seriously defend that as an "excellent" feature. First, because
> it hoists over binders, but also second, because it allows access to an
> uninitialized variable without causing an error (and this being bad is
> where Dave seems to disagree).
> Are you implying that my arguments are not serious? :-(

You are not defending the first part, are you? ;)

> > Then there is the other kind of "hoisting" that merely defines what the
> lexical scope of a declaration is. The reason we need this
> backwards-extended scope is because we do not have an explicit let-rec or
> something similar that would allow expressing mutual recursion otherwise --
> as you mention. But it does by no means imply that the uninitialized
> binding has to be (or should be) accessible.
> No, it doesn't. I'm not interested in arguments about the "one true way"
> of programming languages. I think both designs are perfectly defensible.
> All things being equal, I'd prefer to have my bugs caught for me. But in
> some design contexts, you might not want to incur the dynamic cost of the
> read(/write) barriers -- for example, a Scheme implementation might not be
> willing/able to perform the same kinds of optimizations that JS engines do.
> In our context, I think the feedback we're getting is that the cost is
> either negligible or optimizable, so hopefully that isn't an issue.

Right, from our implementation experience in V8 I'm confident that it isn't
in almost any practically relevant case -- although we haven't fully
optimised 'let', and consequently, it currently _is_ slower, so admittedly
there is no proof yet.

But the other issue, which I worry you dismiss too casually, is that of
> precedent in the language you're evolving. We aren't designing ES1 in 1995,
> we're designing ES6 in 2012 (soon to be 2013, yikes!). People use the
> features they have available to them. Even if the vast majority of
> read-before-initialization cases are bugs, if there are some cases where
> people actually have functioning programs or idioms that will cease to
> work, they'll turn on `let`.
> So here's one example: variable declarations at the bottom. I certainly
> don't use it, but do others use it? I don't know.

Well, clearly, 'let' differs from 'var' by design, so no matter what,
you'll probably always be able to dig up some weird use cases that it does
not support. I don't know what to say to that except that if you want 'var'
in all its beauty then you know where to find it. :)

>> - It binds variables without any rightward drift, unlike functional
> programming languages.
> >
> > I totally don't get that point. Why would a rightward drift be inherent
> to declarations in "functional programming languages" (which ones, anyway?).
> Scheme:
>     (let ([sq (* x x)])
>       (printf "sq: ~a~n" sq)
>       (let ([y (/ sq 2)])
>         (printf "y: ~a~n" y)))
> ML:
>     let sq = x * x in
>       print ("sq: " ^ (toString sq) ^ "\n");
>       let y = sq / 2 in
>         print ("y: " ^ (toString y) ^ "\n")

I don't feel qualified to talk for Scheme, but all Ocaml I've ever
seen (SML uses more verbose 'let' syntax anyway) formatted the above as

    let sq = x * x in
>     print ("sq: " ^ toString sq ^ "\n");
>     let y = sq / 2 in
>     print ("y: " ^ toString y ^ "\n")

Similarly, in Haskell you would write


       let sq = x * x
>        putStr ("sq: " ++ show sq ++ "\n")
>        let y = sq / 2
>        putStr ("y: " ++ show y ++ "\n")

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20121227/2ce45236/attachment-0001.html>

More information about the es-discuss mailing list