7 ms·
However, your complaint seems not to be about closures or shared activation objects per se, but rather about the lack of block-level scope. Bingo, reread my fi
by cousin_it 18y ago
However, your complaint seems not to be about closures or shared activation objects per se, but rather about the lack of block-level scope.
Bingo, reread my first comment.
If closures "trapped" outer values at their current state, then no matter how you called thing.set(), it would always return "foo" from thing.get().
No I don't want hyper-static environments, this would preclude the very useful encoding of objects with mutable state as closures.
Since "j" is created inside a set of braces, you seem to suggest that there ought to be multiple "j" variables created... every "while", "for", "switch", "if", and "else" would have to create an activation object, which would get quite expensive and complicated.
Do you think Ocaml heap-allocates a frame for every scope entered? How is it about as fast as C++, then? :-) Activation frames would need to be created for only those blocks that directly construct closures, findable by simple static analysis. Almost all other languages with closures do precisely this.
As a rule, the introduction of lexical scope doesn't make languages perceptibly slower. For example, the historical transition of Lisps from dynamic to lexical scope was accompanied by fears very similar to yours, and Scheme played a major role in convincing people that lexical scope worked fast. Modern Scheme compilers are quite clever at eliminating unneeded activation frames and closures, sometimes even converting closures into inline code. It's a well-researched topic. (See http://www.paulgraham.com/thist.html http://www.paulgraham.com/thist.html, a great retrospective by one of the best implementers... search for "tied up" for an amusing paragraph about exactly this. The year was 1982, I was busy being born.)
And to reiterate my point from another comment, all code that relies on function scope could be converted to a hypothetical lexically-scoped-JavaScript by a trivial transformation: move every var declaration to the toplevel of the containing function (which coincides nicely with Crockford's advice). This demonstrates that function scope is not more useful than lexical in any practical sense.
In short, I know how JavaScript works, I know how it could work differently, and I consider the different way superior both in theory and in practice.
- IsaacSchlueter 18y agoI guess it just seems much more elegant and simple to me to have only one kind of scope in the language. One is all you need. No, closures refer to the j variable that doesn't get incremented, only assigned to. "Doesn't get incremented, only assigned to." I don't know what that means. How is "i++;j=i;" any different, really, than "i++;j++"? The assignment is by value - no vars get "passed by reference", whatever this means. "Passed by reference" ==> all the closures reference the same "j" variable. The phrase "pass by reference" is, of course, a bit of a mixed metaphor, since it's not really "passed" as an argument to a function, but rather trapped by a closure. Same difference. The actual issue is that all invocations of the loop body alias the same var j, even though it's declared inside the block. "Even though"? There are no blocks in javascript; only functions create scope. That's what's so awesomely simple about this language. Eh, to each his own, I guess. Lexical scope could be introduced in the new additions to ES3.1, but I'm pretty sure it won't be. A javascript engine would be crazy to try to shoehorn it into the language now, since it would, in fact, break a lot of code in the wild. Time to man up. :) Modern Scheme compilers are quite clever at eliminating unneeded activation frames and closures, sometimes even converting closures into inline code. Isn't that roughly what tracemonkey does?
- cousin_it 18y agoIsn't that roughly what tracemonkey does? Yes. Nice to see implementations are growing up. I guess it just seems much more elegant and simple to me to have only one kind of scope in the language... That's what's so awesomely simple about this language. Block scope can be viewed as only one kind of scope. :-) If you try to define a language formally, function scope and lexical scope will be about equivalent on the simplicity scale: scopes will just be tied to code blocks instead of functions. (The scope nesting machinery is needed for closures anyway.) Implementation simplicity is also about equivalent: yes, blocks have to allocate activation frames only if they're needed, but same applies to functions once you get serious about speed. The preference depends on your coding style. I find it intuitive to declare each variable in the outermost {} block that uses it, and not higher up; this intuition exactly corresponds to the formal concept of block scope. Many people naturally think like me, hence the huge number of Web articles complaining about the JS loop scope gotcha, calling it "weird", "unintuitive" and all manner of names. But as you say, to each his own. A javascript engine would be crazy to try to shoehorn it into the language now, since it would, in fact, break a lot of code in the wild. Yes. :-(