On Dec 26, 2012, at 7:40 PM, Brendan Eich <bren...@mozilla.com> wrote:

>> Many also believe that hoisting is an excellent feature, not a weirdness.
> 
> For functions, I can defend hoisting, although if I had had more time, I 
> might have done a let ... in ... or BCPL'ish equivalent form that groups the 
> recursive bindings. For vars hoisting is pretty much an implementation 
> abstraction leak in JS1 :-P.

I absolutely can defend hoisting. (It's hoisting to *function scope* that's the 
issue, not hoisting itself.) Here's the rationale:

- JS is dynamically scoped, so having an implicit dummy value isn't a problem 
for the type system.

- It automatically makes forward references work, so you can:
* order your definitions however it best "tells the story of your code," rather 
than being forced to topologically sort them by scope dependency
* use (mutual) recursion

- It binds variables without any rightward drift, unlike functional programming 
languages.

This is such a simple, practical, and elegant win that Scheme goes halfway 
towards the JS hoisting semantics by having nested definitions:

    (lambda ()                   ;; function() {
      (define (f) (g))           ;;     let f = function() { return g() }
      (define (g) (f))           ;;     let g = function() { return f() }
      (f))                       ;;     return f() }

and last I heard, Racket in fact has gone the rest of the way -- it's moved 
*towards* the hoisting semantics by allowing definitions (i.e., declarations) 
and expressions to intermingle:

    (lambda ()                   ;; function () {
      (define (f) (g))           ;;     let f = function() { return g() }
      (printf "hello world~n")   ;;     console.log("hello world");
      (define (g) (f))           ;;     let g = function() { return f() }
      (f))                       ;;     return f() }

Yes, that's right, JS beat those hoity-toity Schemers to it by over a decade! 
And in fact, the initial binding of a variable in Racket is the #<undefined> 
value! Sound familiar? :)

To be fair, I haven't kept up with the changes in Racket in recent years, so I 
don't know if there are some cases where it does a dynamic error instead of 
returning #<undefined>. But my point here is just that JS isn't alone in doing 
hoisting. It's actually a very sensible design -- it falls out naturally in a 
non-lazy, dynamically typed language with any kind of mutually recursive 
bindings.

Dave

_______________________________________________
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss

Reply via email to