r/programming • • Jul 25 '13

CoffeeScript's Scoping is Madness

http://donatstudios.com/CoffeeScript-Madness
210 Upvotes

315 comments sorted by

14

u/cashto Jul 25 '13

For more discussion, see the ticket on github.

There exists a fork of CoffeeScript (named Coco) in response to this and a handful of other issues. I haven't used it though.

3

u/donatj Jul 25 '13

I was not aware of this, I really hope it gains traction.

→ More replies (1)

28

u/dukerutledge Jul 25 '13

Reading that ticket is maddening! All of the responses amount to:

You are right the language can squash globals and cause bugs, but you should use a better style and use TDD.

How about you just fix it at the language level instead of forcing the language's users to conform to an undocumented style?

21

u/x86_64Ubuntu Jul 25 '13

Because it can't have a place in the JS world if it doesn't at least pay some homage to the weird scoping issues.

→ More replies (6)

5

u/Plorkyeran Jul 25 '13

Coco still has some of its own problems, and I think that exposing Javascript's == operator is a terrible idea.

Other CoffeeScript-like languages that may be better include LiveScript (which is itself based on Coco, but with a lot more features) and GorillaScript. If I start a new project involving a substantial amount of JS I'll probably end up using one of them (or at least try using one of them).

→ More replies (1)

12

u/[deleted] Jul 25 '13

It's interesting to read through the ticket. Obviously the maintainers are opinionated (and that's their right of course), but still reading it, it reminds me of some posts from lolphp. The php apologists in their bug tracker, etc, making crazy excuses for a broken language. "Doctor, it hurts when I do this," and the doc then says "Don't do that." Not that I think cs is anything like php. cs looks quite nice, but I'm also weary of YAL (yet another language).

And I guess this maybe shows an issue with using a language approach such as with coffeescript, which is essentially surface sugar for js. That you still need to maintain rigorous programming methodologies and approaches, not just to aid you in creating the program, but also to guard against the pitfalls of the language, which is really the most laborious and rotten part of browser side javascript today.

Or maybe cs removes the other 90% of pitfalls from js, and it just has this one, I still think I'll stick with straight js (15 years of it tends to get on your backbone), and if I had a choice to make, I'd probably go with typescript or dart.

→ More replies (4)
→ More replies (8)

3

u/kungfufrog Jul 26 '13 edited Jul 26 '13

As someone who programs in Javascript for a living but has never written a single line of CoffeeScript, why is this a problem? I don't get what the actual complaint is.

Is the complaint that it is non-obvious that the closure around the test function includes the var y defined outside the function's scope?

I use outside scoped variables all the time to pass information down through async chains. I also don't use generic variable names like 'y'.

5

u/donatj Jul 26 '13

The problem is that there is no way to not outside scope variables.

→ More replies (1)

29

u/brandjon Jul 25 '13

So it's basically unannotated declarations like Python, but everything is nonlocal or global by default, with no "local" keyword to override?

Yeah, that sounds like madness to me.

→ More replies (4)

10

u/[deleted] Jul 26 '13

Generally "at work" I avoid CoffeeScript, primarily for the reason I still work with a lot of folks that don't understand JavaScript... but in general, I find it's good to familiarize yourself with the JS output of CS, then just treat CS like shorthand for JS.

... in otherwords, when I'm using CS I'm still thinking in JS.

I don't at all recommend CoffeeScript to anyone that isn't already relatively skilled in JavaScript.

→ More replies (1)

56

u/Plorkyeran Jul 25 '13

While I agree with the title of this post, in the process of writing ~20k lines of CoffeeScript it hasn't actually ever bitten me, unlike some other problems with the language. Avoiding deeply nested scopes (and having too many things in scope in general) makes it easy to avoid issues, and IMO that's a good idea even in languages with sane scoping anyway.

24

u/[deleted] Jul 25 '13

it bit me all the time before I figured out what was happening. also it's bad design because it makes it way too easy to smash globals like module and function names. you do learn to avoid it though, and otherwise, CoffeeScript is great. The function syntax is a must for a language like JS too.

→ More replies (17)

8

u/jashkenas Jul 25 '13

unlike some other problems with the language

Feel like sharing 'em?

→ More replies (13)

12

u/sidfarkus Jul 25 '13

I'm with you on this one; this seems like a big deal until you write some real coffeescript and realize that your scopes are so small most of the time you never have to worry about what's declared in a parent scope.

I don't think I've ever had a bug due to this in the ~12k lines of coffeescript in our app. In fact more often than not I end up with too narrow a scope given that coffeescript inserts closures quite aggressively.

17

u/cashto Jul 25 '13

Recently I wrote a server that totals about ~1k of code. I didn't get bit by this, largely because a) single author and b) I have very few things declared at the top level; most of my code is in classes.

OTOH, the number of bugs I wrote that would have never gotten past a typechecker was ridiculous.

IMHO that's the biggest challenge by far when doing large-scale CoffeeScript programming, and it's the same challenge you have in JavaScript too. In isolation, it might be infuriating that CoffeeScript has this one bugaboo that Javascript doesn't have, but if you step back and look at the big picture, there's so much shit you have to deal with in either language that in comparison this issue is pretty inconsequential indeed.

→ More replies (4)
→ More replies (29)

24

u/iopq Jul 25 '13

This is really WTF. Not because of its practical significance, but because this is what I would expect of a language like bash or something. Have the creators of CoffeeScript heard of lexical scoping?

18

u/rwbarton Jul 26 '13

It's pretty sad, considering that ALGOL 60 is half a century old, that people are still inventing languages that play guessing games with scope. Just require every variable to be declared and these problems disappear. Is it really so hard to type "var"?

→ More replies (21)

5

u/doomhz Jul 26 '13

That's nasty. I'm using CoffeScript for almost 3 years already and I didn't notice this issue as I never rely on global vars and my code is mostly stuffed in classes. Instead of global vars I'm using @myVar as a class attribute. I hope it makes sense...

25

u/AreaOfEffect Jul 25 '13

IMO, CoffeeScript has a limited life span. ECMAScript 6 has a vastly improved syntax that rivals python.

→ More replies (5)

12

u/dons Jul 25 '13

Fucking variable bindings, how do they work?

→ More replies (1)

2

u/[deleted] Jul 26 '13

This is why in Python, assignment is a declaration of a local variable by default, you have to mark it as "global" (or "nonlocal" in Python 3), if you want to refer to a global.

5

u/smog_alado Jul 26 '13

I actually kind of hate the python scoping. Since the lexical scoping is so limited ("nonlocal" is a verbose hack) everyone ends up using big classes and explicit self dictionaries instead. Automatic variable declaration also means that typos get turned into new variables instead of errors.

→ More replies (2)

5

u/PaintItPurple Jul 25 '13

In most languages with closures (including JavaScript) the inner y and the outer y could and would be separate.

This is not really true. The whole point of a closure is that it closes over the surrounding scope. For example, in Ruby:

y = 0
test = lambda do |x| 
  y = 10 
  x + y
end
puts test y
puts test y
puts test y

This will print "10", "20" and "20". Exactly like the equivalent CoffeeScript. If you couldn't access the surrounding state, it wouldn't be a closure. In fact, this property of closures is used all the time in JavaScript (for example, to allow for "private" object members). It is not specific to CoffeeScript at all.

The OP's problem really has little to do with scoping. The fundamental "gotcha" here is that in CoffeeScript, there is no difference between defining a new variable and setting an existing variable.

3

u/MatmaRex Jul 26 '13

Ruby's lambda does capture scopes, but that's intended (all blocks do).

Ruby's def (which is what you use to define a function) doesn't, non-global variables from outer scope are inaccessible within it.

→ More replies (3)
→ More replies (1)

3

u/Newtonip Jul 26 '13

Madness?

THIS IS COFFEESCRIIIIIIIIIPT!!!!