23 ms·
FWIW this is how CS works: top_level_variable = null f = -> top_level_variable = "hello" f() console.log top_level_variable # prints hello
by showell30 15y ago
FWIW this is how CS works:
top_level_variable = null
f = ->
top_level_variable = "hello"
f()
console.log top_level_variable # prints hello
- cheald 15y agoThe concern is that because Coffeescript automatically scopes variables to the scope of their first reference, it can introduce maintenance issues. Consider the following: foo = -> bar = "woot!" console.log bar This compiles to: var foo; foo = function() { var bar; bar = "woot!"; return console.log(bar); }; bar is locally scoped to foo(). Now, 2 weeks later and 200 lines earlier, you come along and define: bar = -> alert "Holy crap cheese is awesome!" Which compiles to: var bar, foo; bar = function() { return alert("Holy crap cheese is awesome!"); }; foo = function() { bar = "woot!"; return console.log(bar); }; Now, all of a sudden, the "bar" reference in foo isn't scoped to foo() anymore, it's scoped globally, and once you invoke foo(), it'll replace the function bar with a string, potentially breaking your app. It's an ease-of-maintenance issue. This isn't consistent behavior, though. If you define your top-level bar() function after foo, like so: foo = -> bar = "woot!" console.log bar bar = -> alert "Holy crap cheese is awesome!" Then you get "correct" scoping (and the outer bar is shadowed): var bar, foo; foo = function() { var bar; bar = "woot!"; return console.log(bar); }; bar = function() { return alert("Holy crap cheese is awesome!"); }; On one hand, it could be argued that this is a "name things better" problem, but on the other, I have to agree that it'd be nice to be able to explicitly scope things when needed. Given that the behaviors are divergent based on what order the variables appear in, I'd say it's confusing enough that a way to explicitly say "hey, I know what I'm doing, I want to shadow any outer variables and declare local scope here" would be useful.
- mutewinter 15y agoThis is a better explanation of the problem than the blog post. Thanks!
- satyr 15y agoThe inconsistency doesn't stop there; `for` variables are specialcased: bar = -> alert "Holy crap cheese is awesome!" foo = -> for bar of bars console.log bar return ↓ var bar, foo; bar = function() { return alert("Holy crap cheese is awesome!"); }; foo = function() { var bar; for (bar in bars) { console.log(bar); } };
- cheald 15y agoThat makes plenty of sense to me; when do you ever want to leak a for loop counter to an outer scope?
- satyr 15y agoAnd when do you ever want to leak local variables to an outer scope? Never. Not to mention that loop counters are no different than other `var`iables in JS.
- cheald 15y agoYou do want to sometimes reference outer scope variables from inner scopes, though. The only difference between a leaked local and a properly referenced global is usage semantics.
- boundlessdreamz 15y agoThanks for this! Way better explanation than the blog post :) Is there anyway to make the scope explicit in coffeescript?
- cheald 15y agoNo. That's the crux of the complaint. In plain Javascript, you can use "var x" to scope x to the current scope (and in 1.7, you can use 'let' to scope to the current block, not just to a function), but there's no corollary in Coffeescript, since Coffeescript manages scoping for you automagically. It's a convenience 99% of the time, but the 1% of the time that it's not, it's a giant pain in the ass. If there were something like var/let/local, you could solve the problem manually, but as the Twitter exchange indicated, there is no plan to add it. The solution/workaround is "use descriptive names and avoid polluting scopes", but the reality of software development is that you're eventually going to cross those wires, and it's going to make you crazy until you figure out what happened.
- yxhuvud 15y agoYes, create the variable as a function argument.
- cheald 15y agoWhile that does allow you to use a locally scoped variable (even one that shadows an outer variable), it's still not explicit scoping.
- showell30 15y agoThere is some discussion here on why a "bar" variable at top level only affects the scoping of other "bar" variables that are lexically below "bar" in the file, not above it. https://github.com/jashkenas/coffee-script/issues/1121 https://github.com/jashkenas/coffee-script/issues/1121