TE
TechEcho
Home24h TopNewestBestAskShowJobs
GitHubTwitter
Home

TechEcho

A tech news platform built with Next.js, providing global tech news and discussions.

GitHubTwitter

Home

HomeNewestBestAskShowJobs

Resources

HackerNews APIOriginal HackerNewsNext.js

© 2025 TechEcho. All rights reserved.

The Problem with Implicit Scoping in CoffeeScript

133 pointsby michaeltyover 13 years ago

17 comments

mhansenover 13 years ago
I'll copy below jashkenas' longer answer from the old github issue about this, <a href="https://github.com/jashkenas/coffee-script/issues/712#issuecomment-430673" rel="nofollow">https://github.com/jashkenas/coffee-script/issues/712#issuec...</a><p>"""<p>Sorry, folks, but I'm afraid I disagree completely with this line of reasoning -- let me explain why:<p>Making assignment and declaration two different "things" is a huge mistake. It leads to the unexpected global problem in JavaScript, makes your code more verbose, is a huge source of confusion for beginners who don't understand well what the difference is, and is completely unnecessary in a language. As an existence proof, Ruby gets along just fine without it.<p>However, if you're not used to having a language without declarations, it seems scary, for the reasons outlined above: "what if someone uses my variable at the top of the file?". In reality, it's not a problem. Only the local variables in the current file can possibly be in scope, and well-factored code has very few variables in the top-level scope -- and they're all things like namespaces and class names, nothing that risks a clash.<p>And if they do clash, shadowing the variable is the wrong answer. It completely prevents you from making use of the original value for the remainder of the current scope. Shadowing doesn't fit well in languages with closures-by-default ... if you've closed over that variable, then you should always be able to refer to it.<p>The real solution to this is to keep your top-level scopes clean, and be aware of what's in your lexical scope. If you're creating a variable that's actually a different thing, you should give it a different name.<p>Closing as a wontfix, but this conversation is good to have on the record.<p>"""
评论 #3381653 未加载
评论 #3381861 未加载
评论 #3396094 未加载
评论 #3382080 未加载
评论 #3381892 未加载
gcvover 13 years ago
It's worth pointing out that JavaScript 1.7 resolves this mess by introducing block scoping using the "let" keyword. It works just like it does in Scheme, Common Lisp, and Clojure (i.e., correctly). Not supported in anything except Firefox, unfortunately.
评论 #3380467 未加载
rayinerover 13 years ago
Scheme got this right in 1970. There is no excuse to design a new language this way.
评论 #3380087 未加载
评论 #3380336 未加载
limeblackover 13 years ago
Another Issue:<p>Although the following examples could become unambiguous with parenthesis, these examples demonstrates how a trivially overlooked ending delimiter further complicated the language. Not only is the intent of the CoffeScript code unclear in the examples below but the slight variation in the CoffeScript, produces radically different output. The CoffeeScript differences are so small it would be easy for someone to add accidentally while editing. Anonymous function passing and function calling in Javascript require no additional wrappers or edits, while in CoffeeScript you must add special case clarity.<p><a href="http://img542.imageshack.us/img542/7379/coffeescripttojavascrip.png" rel="nofollow">http://img542.imageshack.us/img542/7379/coffeescripttojavasc...</a>
oinksoftover 13 years ago
<i>@mitsuhiko Not gonna happen ;) Forbidding shadowing altogether is a huge win, and a huge conceptual simplification.</i><p>How arrogant! You'd think he'd step back for a second and consider the suggestion, but it sounds like he's on autopilot.
评论 #3380423 未加载
评论 #3380212 未加载
评论 #3380144 未加载
评论 #3381864 未加载
评论 #3380217 未加载
评论 #3381305 未加载
评论 #3380114 未加载
stoodderover 13 years ago
Why not allow CoffeeScript to use the 'var' keyword, explicitly telling CS that this variable should be scoped locally even though it may be shadowing another variable? This seems consistent with their approach of allowing (although optional) native javascript syntax such as {}, and []. This still allows CS to stick to it's paradigm of forbidding shadowing unless we explicitly state that we know what we're doing.
评论 #3381948 未加载
tjholowaychukover 13 years ago
I like the look of coffeescript's assignment better, but I cant help but think "let" is much less ambiguous, once you see it you look no further. This reminds me a bit of Ruby, where "foo" could be a function or variable potentially from anywhere so it's a little unclear although better looking.
leafoover 13 years ago
Look at how MoonScript handles this: <a href="http://moonscript.org/reference/#the_using_clause_controlling_destructive_assignment" rel="nofollow">http://moonscript.org/reference/#the_using_clause_controllin...</a><p>I didn't want to change the default semantics, but I wanted to have a way for the programmer to be safe if they wanted to, so I created the `using` keyword for function declarations.<p>You explicitly declare what you intend to overwrite in the lexical scope, including overwriting nothing at all with `using nil`.
buddydvdover 13 years ago
I found one of the referenced links in Github issue #712 quite interesting:<p><a href="http://www.rubyist.net/~matz/slides/rc2003/mgp00010.html" rel="nofollow">http://www.rubyist.net/~matz/slides/rc2003/mgp00010.html</a><p>Source: <a href="https://github.com/jashkenas/coffee-script/issues/712#issuecomment-979127" rel="nofollow">https://github.com/jashkenas/coffee-script/issues/712#issuec...</a>
评论 #3380779 未加载
gerggergover 13 years ago
<i>Considering we won't see this changed since the author has already closed the issue and expressed his satisfaction with the current rules this article should at least serve as a reminder for errors not to repeat with the next language someone designs.</i><p>It's open source. Why not fork it and get some like minded coders to change it with you?
评论 #3380479 未加载
评论 #3380418 未加载
danmaz74over 13 years ago
With "var" and shadowing you can still shoot yourself in the foot, it's just the other foot.<p>If you need global variables, it's sensible to just adopt a simple naming convention, like prepending g_ (or whatever pleases you) to all your variables. I already did that with plain JS and it's well worth the "effort".
latchkeyover 13 years ago
Kind of a side note to the posting, but I just have to say: Please make your usage of parens consistent. If you aren't going to use them, don't use them everywhere.<p>Here is an example of what I'm talking about:<p>if isAir cx, cy, cz + 1 then addPlane('near', block)<p>Should be:<p>if isAir cx, cy, cz + 1 then addPlane 'near', block<p>Personally, I use them everywhere because I like having the stronger visual clue that this is a method I'm calling. I think making them optional in CS was a bad idea.<p>if isAir(cx, cy, cz + 1) then addPlane('near', block)<p>imho, so much more readable.
评论 #3380116 未加载
showell30over 13 years ago
CoffeeScript's approach toward top-level variables is quite elegant and simple. When you declare a variable at top-level scope, it is equally available to all code within that file for both reading and writing, with no strange "nonlocal" or ":=" syntax to complicate manners.<p>Once you understand the reach of CoffeeScript's top-level variables, it is easy to write bug-free code. Since you know that top-level variables have wide scope, you simply need to be judicious about putting variables at top-level scope. If a variable is not needed at top level scope, don't put it there.
评论 #3380055 未加载
perfunctoryover 13 years ago
This is my biggest problem with CoffeeScript. And the author stubbornly refuses to fix it. Apparently it's some sort of Ruby religion.
shaunxcodeover 13 years ago
Here is a ghetto "let" form in coffee<p>((a = 5, b = 6, log = x -&#62; console.log x) -&#62; log a + b)()
cvshepherdover 13 years ago
&#62; The simple solution is to either add a nonlocal keyword like Python has or to introduce a := parameter that works like = but explicitly overrides a higher level variable.<p>I disagree. The simple solution to this is to write tests.
评论 #3382018 未加载
showell30over 13 years ago
FWIW this is how CS works:<p><pre><code> top_level_variable = null f = -&#62; top_level_variable = "hello" f() console.log top_level_variable # prints hello</code></pre>
评论 #3380326 未加载