
Why CoffeeScript Isn't the Answer - jhack
http://www.walkercoderanger.com/blog/2014/03/coffeescript-isnt-the-answer/
======
crazygringo
I used CoffeeScript full-time for a year, both client-side and server-side
(node.js). I completely agree with everything here -- it's a _great_ summary,
and it describes exactly while I never, ever want to use it again.

In CoffeeScript, ambiguous code is the rule, not the exception. On top of
that, things like variable capture and everything-returns-a-value introduce
new kinds of bugs. The author says "realistically, the issues I have raised
with CoffeeScript don’t come up every day," but in my experience they pretty
much did.

But the real kicker on top of it all is that none of the stuff is documented.
When you're trying to guess if you should use parentheses or a comma or an
indent or a newline or a backslash or _what_ , there are no reference
documents to help you. The CoffeeScript home page just has a bunch of tutorial
examples which give you an overall idea, but there's nothing rigorous, and the
devil is in the details when you start combining aspects of the syntax.

In the end, I'm much more productive programming in JavaScript because I know
_exactly_ how the language works, no surprises. JavaScript has its fair share
of warts, but you take a day or two to learn them, and then you never need to
worry about them again. CoffeeScript, on the other hand, is just endless
surprises. And I still felt that way after a whole _year_ of using it at work.
It's basically unlearnable -- no matter how much experience you have, you
constantly find yourself pasting different versions of a line into the "try"
tab of [http://coffeescript.org/](http://coffeescript.org/) until you get one
which, through trial and error, turns into the JavaScript code you want.

~~~
ilaksh
You completely agree with everything he wrote, after a year full-time? Really?

So you would use curly braces and commas to specify an object, and then be
confused when CoffeeScript doesn't get it?

After a year you didn't figure out that its a best practice to leave off the
parenthesis in just the outermost function call, but to include them in the
other calls on a line to make things clear?

After a year, you didn't realize that with the CoffeeScript scoping rules, you
couldn't just throw in a global at the last second without looking carefully
to see if it was used somewhere else?

After a year, you still hadn't learned about function binding with fat arrow?

After a year, you still hadn't learned that the existential operator (?) means
you don't have to use typeof nearly as much?

~~~
crazygringo
Ha! Not necessarily those specific examples, but the overall reaction to it.
Here are a couple of other articles which explain the same things:

Section "full of surprises": [http://ruoyusun.com/2013/03/17/my-take-on-
coffeescript.html](http://ruoyusun.com/2013/03/17/my-take-on-
coffeescript.html)

[http://ceronman.com/2012/09/17/coffeescript-less-typing-
bad-...](http://ceronman.com/2012/09/17/coffeescript-less-typing-bad-
readability/)

And here's an old HN comment of my own which described a few representative
difficulties:
[https://news.ycombinator.com/item?id=4518892](https://news.ycombinator.com/item?id=4518892)

Also, there's no such thing as a global in CoffeeScript (unless you explicitly
specify window.xyz), since everything is scoped to the file. And that's the
point -- it's ridiculous to have to "look carefully" at all your code to see
if functions further down share a variable name _inside of them_. In
JavaScript, you don't need to worry about that because you know "var" scopes
each variable to its function, regardless of whether a higher function or
global variable uses the same name. In CoffeeScript, you suddenly _do_ have to
worry about that, which is fairly insidious and bug-prone behavior.

~~~
ilaksh
Hm.. well you may want to use more precise language in the future, because you
said you "completely agree" and that it describes "exactly".

So you are saying that none of those particular issues are problems you are
having today with CoffeeScript or were problems for most of the year?

In which case, what problems did you have?

Edit: it looks like in another thread you are pointing out some random and
unmaintainable code examples that are ambiguous and saying that its hard to
know how they will be interpreted by the compiler. Its hard to know how those
examples would be interpreted by anyone, or why you would write code like that
and create that problem for yourself.

------
couchand
This article proves not that CoffeeScript is flawed but that Jeff Walker
doesn't understand how to use it. For instance, his first example is:

    
    
        # BROKEN
        func 5, {
           event: (e) -> 
             if e.something
               36
             else
               45,
           val: 10}
    

Anyone with more than a day's experience with CoffeeScript knows that it's
much better to express this with the simpler:

    
    
        # far better
        func 5,
           event: (e) -> 
             if e.something
               36
             else
               45
           val: 10
    

Note how just dropping the excessive notation makes the intention clearer
while also making the code cleaner.

His example on variable capture neatly illustrates a few of the opinions of
CoffeeScript that actually make it far easier to reason about code: don't use
global variables, and if a variable has the same name, it should refer to the
same thing. It's far more confusing to allow rampant variable shadowing. Code
that relies on variable shadowing is simply broken.

His last example shows a fundamental misunderstanding of not just
CoffeeScript, but JavaScript generally. Granted `this` binding can be
sometimes confusing, which is why CoffeeScript has a fat arrow (`=>`) to
automatically capture `this`.

~~~
ilaksh
"More than a day's experience" is not really fair.

It took me months to really get used to CoffeeScript, and I certainly left in
a few unnecessary commas after the first day.

The rest of what you wrote I agree with.

But I think the problem is that people are dismissing CoffeeScript before they
have learned it, just like I did originally.

I now vastly prefer to use CoffeeScript (or rather ToffeeScript these days,
but thats another issue) whereas initially I thought that CoffeeScript was a
joke.

Then I had to learn CoffeeScript because it was used in a library that I
needed to understand.

It was only _after_ I had invested the time in learning CoffeeScript that I
could see the advantages. In fact, up until that point that I had learned it,
CoffeeScript _was not_ an advantage for me -- it was a liability, because I
didn't know how to use it. When you aren't familiar with a language then
whatever advantages it may have are more than offset by the fact that you
don't know what you are doing.

I think this is a problem that pretty much every new paradigm shares to some
degree. It is very difficult for the average person to emotionally get behind
the effort to learn a new way of doing things, and psychologically we just
aren't wired to make an accurate judgement about whether that will pay off.

Judgments and decisions are actually emotional/subconscious and the
rationalization comes afterward.

~~~
fat0wl
the minutia of most efficiently optimizing your syntactic sugar to communicate
DEEEEP meanings is the most annoying part of the open-source/language
community & one of the biggest factors in why i've actually come to like
corporate java.

i've been on so many RoR interviews where i am dismissed essentially for not
knowing enough of cutesy syntax tricks and yet in the Java + plain ol'
javascript projects i've worked on I've been exposed to a muuuuuch wider
variety of programming design patterns than i ever was in Ruby-land, to the
point where i could care less about the tiny semantics these hipsters spout on
about

one of the few new languages i'm interested in working with now is Clojure
simply because they cleanly define libs & then don't have all of this
obsessive "syntactic sugar" nitpicking. to make a language / code library
usable it shouldn't depend on developers going down a rabbit hole of brackets
etc. I understand this is difficult to avoid in the "compile to js"/language
pre-processor community but it's why I prefer Dart as a solution. It is an
attempt at a clean, robust, simple language rather than a repeat of the
annoying language evolution process where devs in the know just talk down to
those who don't care to commune with punctuation all day

------
shittyanalogy
It's a tool, that is all.

 _Ambiguous code_ is a poorly thought out contrived example with a simple
solution.

To me, this:

    
    
        eat food for food in foods when food isnt 'chocolate'
    

Is kind of beautiful and much more readable than:

    
    
        for (var i = 0, var len = foods.length; i < len; i++) {
          var food = foods[i];
          if (food !== 'chocolate') {
            eat(food);
          }
        }
    

How is this even an argument?: _" One wouldn’t realize it was conditional
until reading the end."_ How do you expect to understand any code without
reading it? How do you understand people when they talk without listening? And
the whole paragraph is moot with syntax highlighting.

Variable clobbering is javascript's problem not coffescript's.

ECMAScript 6 introduces a syntactic sugar for classes as well as like every
single JS framework.

Knowing plain old JS is important, especially for understanding CS. CS is just
a tool that some people find useful, I don't really understand the passion or
frustration.

~~~
olalonde
Your Javascript example is a bit contrived too. How about:

    
    
      foods.filter(function (e) { return e !== 'chocolate'; }).forEach(eat);
    

Regardless, I disagree that the Coffeescript example is more readable. My
brain is much faster at parsing symbols (`(`, `{`, etc.) than english words.

With your JS example, without having to read the words, I know there's a loop,
a conditional and a function invocation. I also know that I can safely add
statements after this piece of code without worrying it might break some other
function (in Coffeescript, I'd have no way to tell if the implied return
really mattered or not assuming it was the last line of a function).

With your CS example, I have no way to tell what's going on until I've read
the full sentence. I have to read every word and see if it matches one of the
many reserved keywords in order to determine if it has a special meaning or if
it's just a regular variable.

In Javascript, you have a few reserved words but the list is relatively short
and those words are almost always preceded by a line break or a symbol.

Maybe our brains work differently...

~~~
colbyh
I'm obliged to agree. Even the "contrived" example is easier for me to parse
given that I have years of seeing "{}[]()" as delimiters.

Not to mention that filter/each functions will get even easier to parse once
es6 standards reach the browser (stabby procs, woo).

~~~
shittyanalogy
I don't understand. Because you have been doing something one way for years, a
different way is harder and thus worse?

I'm not trying to be inflammatory at all just wondering as this is a reply to
my comment.

------
hhsnopek
Ok, so if CoffeeScript is just JavaScript, add the parenthesis. If you need
brackets to make a section of code readable or compile to "certain"
JavaScript, then add them. Even the programs I work on we add parenthesis,
brackets, etc for readability. Use CoffeeScript to increase productivity.
Nowhere does CoffeeScript say you must use white space instead of brackets and
such. Keep it simple and easy, classes are also nice; I'll be reading those
are articles soon as well to gain less of a bias.

~~~
InclinedPlane
There are still two sides in programming, it seems. And interestingly enough
it's not necessarily static vs. dynamic or procedural vs functional.

One the one hand you have pragmatic, loosey goosey languages like perl,
javascript, ruby, even scala and C#. An important defining characteristic
being perl's maxim "there's more than one way to do it".

On the other hand you have what I'd call the "bondage and discipline"
languages like python and java. The defining characteristic being "there
should only ever be one right way to do a thing".

In my experience people coming from the 2nd world have a harder time living in
the 1st than vice versa.

~~~
skybrian
It's not that simple if you go beyond surface impressions and common usage.
There are in fact many ways to do the same thing in Java and Python, some
better than others. Both languages have escape hatches that can be used to
extend the language; it just requires more effort.

Reflection and annotation processors in Java are very powerful tools; see
Guice, Dagger, and AutoValue. Creating something like JQuery is awkward in
Java, but it can be done; see GQuery. Java 8 will make functional and
callback-heavy DSL's a whole lot easier to build.

Python may look like a strict language but it's not. You can redefine just
about anything except the core syntax. If you want to make your head spin look
into metaclass programming.

Haskell is a weird one; statically typed, but extremely expressive. It's very
easy for Haskell programmers to define their own obscure notations and like
when reading mathematics, you must understand the definition of every symbol
or you're lost.

One interesting dimension is the attitude towards modifying other people's
libraries. In Java, it's easy to build something that nobody else can change
unless they fork the library and modify the source or mess with the bytecode.
But if you build your own, you can do what you want. In more dynamic
languages, you can load someone else's library and muck with it at runtime.

------
freyr
_> > Why CoffeeScript Isn't the Answer_

What _is_ the question for which CoffeeScript is a compelling answer?

 _" I needed to speak to Germans, so I learned French and spoke through a
French-German interpreter. Things were occasionally lost in translation and
somteimes I couldn't get my point across, but French is prettier. Can I
recreate this experience in code?"_

 _" My team can't learn to write `var` or `===`. Can we just learn a new
language instead?"_

 _" Indentation speaks to my aesthetic sensibilities, but braces do NOT! What
fits my needs?"_

 _" I don't want to use JavaScript. Fortunately, since I never make coding
errors, I'll never need to debug transpiled JavaScript. What's the right
language for me?"_

Seriously, though, what is the problem that CoffeeScript solves?

~~~
ilaksh
[http://en.wikipedia.org/wiki/Status_quo_bias](http://en.wikipedia.org/wiki/Status_quo_bias)

CoffeeScript obviously solves problems. Its not compelling to you because of
status quo bias, and because you don't want to invest the effort to learn it.

The issue with equality is a real issue. CoffeeScript solves that issue.

Braces and parenthesis _do_ become awkward in JavaScript with callbacks.
CoffeeScript solves that problem.

You have been able to debug CoffeeScript as CoffeeScript for some time now
with source maps. However, debugging the generated JavaScript is not hard for
someone who knows JavaScript.

~~~
rubyn00bie
Its cute you link to status quo bias, then immediately state, like a fact from
god that "braces and parenthesis _do_ become awkward (...) Coffeescript solves
that problem."

It's your opinion that coffeescript solves the callback and parentheses issue.
I'd also call your argument a bit of red herring.

... FWIW? I think futures do a mighty fine job of solving callback issues; no
coffeescript needed. Design around them, don't make a whole new "dialect" for
it..

~~~
ilaksh
For callbacks I have found ToffeeScript to be an even bigger improvement than
CoffeeScript. You can write code like this:

    
    
        e, personJson = fs.readFile! "person.json"
        person = JSON.parse personJson
        matchesLastname = myDB.query! "lastname", person.name
        id = msgQueue.push! { JSON.stringify(matchesLastname) } 
        log.info "Message sent to queue: #{id}"
        

instead of this:

    
    
        fs.readFile("person.json", function(e, personJson) {
          var person = JSON.parse(personJson);
          myDB.query("lastname", person.name, function(matched) {
            msgQueue.push(JSON.stringify(matchesLastname), function(id) {
              log.info("Message sent to queue: " + id);
            });
          });
        });
    

Why do you believe that it is better to design around serious issues rather
than creating a new paradigm?

I have found that the best solutions always involve a new/different
fundamental model that incorporates solutions to recurring problems.

~~~
rubyn00bie
I guess I just don't think it's a serious issue. I've found that often when I
have an "issue" it's more so my design lacking not the tool (javascript)
itself.

~~~
ilaksh
What would the code look like for my example using futures in JavaScript?

~~~
TheZenPsycho

        fs.readFile("person.json")
        .then(function(e, personJson) {
            var person = JSON.parse(personJson);
            return myDB.query("lastname", person.name);
        })
        .then(function(matched) {
            return msgQueue.push(JSON.stringify(matchesLastname));
        })
        .then(function(id) {
            log.info("Message sent to queue: " + id);
        });

~~~
ilaksh
That's part of it. What about creating the promises?

~~~
TheZenPsycho
that's in there, with the assumption that you're using the promises based
node.js api, but if you aren't, and you're using Q, that part looks like this

    
    
        var readFile = Q.denodeify(FS.readFile);
    

which doesn't create the promise. it just wraps the readFile method so that it
returns a promise when you call it.

------
berdario
I agree with some the things he writes, but others seem blatant absurdities:

> "the + operator is still both numeric addition and string concatenation.
> That is frequently listed as one of the bad parts of JavaScript. Why no
> provide separate operators for the two?"

The problem isn't operator overloading: the problem is implicit type coercion.

Having to use 2 separate operators/functions for separate types when writing
code, is useful only if types are actually checked at compile time, and the
compiler can do inference on them (see the + and +. operators in F#)

If you have a dinamically typed language, you can have sane semantics if you
make it so that type conversions are explicit (e.g. Python, Ruby...)

See also: [http://james-iry.blogspot.it/2009/03/operator-overloading-
ad...](http://james-iry.blogspot.it/2009/03/operator-overloading-ad-
absurdum.html)

~~~
Dylan16807
The problem is the combination of the two. You can have operator overloading
if conversion is explicit. You can have a converting operator if the action is
explicit. But you can't have loose overloading and automatic conversion at the
same time without silly defects.

Edit: And you didn't just disagree but call it a 'blatant absurdity' to blame
the half of the problem that you happen to like better? Jeez.

~~~
berdario
I agree, "blatant absurdity" is quite a strong wording. I should've wrote
"quite dubious" or the like.

In my defense, I didn't even think of having a language with type coercion and
0 operator overloading (even on builtin types). I never saw such a language,
and I'm skeptical that it could work. But it's an interesting take on the
problem.

I cannot say why I think that the no-coercion+overloading is the better
solution... maybe that's because operators are dyadic, and thus type coercion
can be executed on both sides of the operator, and multiple times. While
function application is (can be?) sort of monadic (in the APL sense) since
coercion/overloading for an argument doesn't depend on the type of the other
arguments supplied to the function

(But while writing this, I'm not so sure anymore... at the very least, it
could depend on the order in which arguments are evaluated...)

~~~
Dylan16807
What I think of here is Lua, where builtin types have no overloading and there
is a single type of coercion, between numbers and strings. This coercion is
only triggered by arithmetic operators and concatenation. Unambiguous and
pretty harmless.

(Technically objects can overload binary operators (with no coercion) but it's
not very common)

------
kevingoslar
This article only proves that when doing it wrong, CoffeeScript causes
problems.

No parenthesis make nested calls unreadable? Simple add parenthesis for the
inner calls. Like in any other language with optional parenthesis (Ruby) too.

Too long statements are unreadable? Don't write them. Maintaining an 80 or 100
character line limit is good coding practice anyways.

~~~
scribu
That's kind of the point of the article: If it's easy to get it wrong in
CoffeeScript, i.e. CoffeeScript has its own bad parts, then you're better off
just learning to deal with the bad parts in JavaScript directly.

------
ceronman
This is not the first article talking about CoffeeScript's ambiguity and
readability issues.

It's interesting how CoffeeScript fans almost always decide to blame the
programmers for these problems. They said good developers should use common
sense and use best practices to make code readable, for example by always
using parentheses when calling functions. I hear exactly the same argument in
the Perl community.

But reality is that if a language allows you to write bad code easily, people
will write bad code, and you will have to read bad code. This is very easy to
verify: most CS project on GitHub, starting with the CS code itself
([http://github.com/jashkenas/coffee-
script](http://github.com/jashkenas/coffee-script)) contain a lot of bad
ambuigous uses of the language. A very similar thing happens with Perl code.

Programming language design is not only about making it easy to write good
code, but also about making it hard to write bad one.

~~~
nebstrebor
It is hard to argue, however, that Javascript (the thing Cofeescript purports
to improve) doesn't "allow you to write bad code easily" or "makes it hard to
write bad code". I have avoided Coffeescript and probably will continue to do
so, but it seems to at least try to make it a bit harder to write bad code,
albeit not getting all the way there apparently.

------
untog
I do have some frustrations with CoffeeScript as outlined here - I find the
unless keyword infuriating because it forces me to read backwards:

    
    
        a = 123 unless b == 2
    

"OK, so a is set to 123. Oh, unless b is 2. That's annoying"

That said, my answer is to just not use the unless keyword. If you don't like
CoffeeScript classes, you don't have to use them. IMO you could write
CoffeeScript using only the kind of functionality availabie in vanilla JS and
it would _still_ be a preferable experience.

~~~
__david__
I really like that syntax, I think it reads well.

Of course, I've known Perl for 20 years, so that might have something to do
with it. :-)

------
darkxanthos
Am I the only one astounded that we're still having this conversation? The
fact that it's still around shows me it has indeed been "the answer" for some.
The fact that it hasn't become ubiquitous is plenty of proof that it also is
not a one size fit all solution, as if any solution is.

------
omaranto
I wonder what the author thinks of GorillaScript [1].

[1]:
[http://ckknight.github.io/gorillascript/](http://ckknight.github.io/gorillascript/)

~~~
dgreensp
Very interesting! I was nodding along through the first dozen syntax features
or so, which seemed much more obvious and well-chosen than CoffeeScript's, and
then they just kept piling on... Promises? Macros? Generics??

I won't prejudge GorillaScript, but if someone ever makes a language like this
that exhibits both good taste and a little more restraint, it could get wide
adoption.

------
RossPenman
"CoffeeScript isn't the answer because I don't understand how it works."

------
philliphaydon
This seems to share many of the same things of CoffeeScript I've had. I prefer
plain old JS. More readable, unless you're looking at twitter bootstrap
code... No semicolons? Such messy code IMO.

------
mrinterweb
I find CoffeeScript very readable, and I highly value readability. The extra
verbosity of JavaScript doesn't really help me when I am reading code. I read
CoffeeScript code faster than I can read JavaScript because CoffeeScript
removes so much of the repetitive boiler plate code and lets you focus on the
intent of the code.

I don't really understand the ambiguity argument. From the code examples in
the article, I get the impression that the author doesn't really understand
CoffeeScript.

I definitely prefer CoffeeScript to good old JavaScript.

------
Daiz
I had a lot of niggles with CoffeeScript as well, which is why my compiles-to-
JS language of choice is LiveScript[1]. It fixes basically all the annoyances
and adds a lot of nice things on top of that. For exmaple, you can write more
paren-free code with it and there are more kinds of useful function
declarations (hushed functions, curried functions, backcalls).

[1] [http://livescript.net/](http://livescript.net/)

------
kin
Mm, most of the issues the article discusses are part of the learning curve of
Coffeescript IMO. The real problem I've had (and I still love it for some
reason) is dealing w/ JS frameworks. Like, try using Coffeescript w/ Angular
or something. It's quite difficult.

------
Roboprog
Disclosure: I have never used CoffeeScript. However, based on the article, the
death-knell against CoffeeScript for me was the variable scoping rules.

With no variable declaration keyword (a la var, my, local, private), adding a
variable assignment anywhere could radically change the variable scoping.

I'm done, this isn't suitable for prime-time, time to go somewhere else.

I spent too many years in the 80s working with xBase. I've been shafted too
many times by calling a (coworker's) routine that forgot to declare its
variables "private", which stomped over one of my variables. (private in xBase
is similar to local in Perl 4) To have a language which doesn't let you
declare the intended scope of a variable - ugh.

~~~
kaonashi
I've used coffeescript extensively for years, and I have never had that be an
issue. Not sure if it's because I rarely write a file longer than ~200 lines,
or I'm careful about variable names and global scope.

More generally I've found that coffeescript mixes much better with a
functional style than with an imperitive one.

~~~
peterashford
This, to me, sounds just like Douglas Crockford when he dismisses all the
evils of Javascript as "things that never happen to him". Which is
interesting, given that they occur to me and my work mates on a fairly regular
basis.

~~~
kaonashi
I don't think the gist is that there aren't problems with these languages, but
that with a little carefully placed construction tape, you can avoid falling
into the large holes.

~~~
peterashford
Yeah, people say the same thing about C++. It's great when you have your own
carefully curated subset of the language.... and then you have to deal with
other programmers & libraries

~~~
kaonashi
The difference being, you can't avoid javascript (if you want to target the
browser); you can either write it directly, or use it as a compile target.
Each has it's strengths and drawbacks.

------
rubiquity
Phew. I was beginning to worry that a whole month would go by without a blog
post about CoffeeScript's deficiencies. I hate it when I write unidiomatic
code in a language and then get punished by said language.

Now that I got my sarcasm out of the way, whenever somebody bashes
CoffeeScripts variable shadowing they openly show the world that they don't
understand how variable scoping _should_ work. CoffeeScript covers up
JavaScript's warts. One of those warts is JavaScript's broken implementation
of closures. CoffeeScript is trying to help you, don't let your lack of
understanding of lexical scope get in its way.

------
klibertp
> The declaration of what food is occurs in the middle of the line and doesn’t
> even look like a variable declaration.

And that's what makes the whole line unreadable. And 'unless' would make it
even less readable.

I can understand why people insist on discussing such personal, subjective
matters as "readability" or "expressiveness" \- I like that too. What I don't
get is why do they confuse their impressions with facts and why do they try to
generalise based on them. Is it that hard to admit that what's readable to you
may be completely unintelligible to someone else?

Comparison of programming languages, outside of some really technical metrics,
will always be subjective and preference-based. Discussing metrics as vague as
"readability" without even agreeing on what it means is absolutely pointless.
Yet so many man-hours go into debates and blog posts, sometimes even books,
which cover such issues. It's stupid, straw-man discussion every single time
it appears.

I really wish people would stop writing lengthy posts with a sole purpose of
informing the world about their preferences. It's not that I'm against people
having preferences, I'd just like them stated as preferences, not facts, and
preferably only when they are not repeated a millionth time this month.

Edit: also, this: [http://joelgrus.com/2013/12/24/why-programming-language-x-
is...](http://joelgrus.com/2013/12/24/why-programming-language-x-is-
unambiguously-better-than-programming-language-y/)

------
ColdHawaiian
> eat food for food in foods when food isn't 'chocolate'

> from the CoffeeScript tutorial...Furthermore, ___until you finish reading
> the line it isn’t clear which foods will be eaten_ __.

The thing with typing the filter at the end is, that format has its basis in
mathematical notation, particularly in set theory. Using an even terser
mathematical syntax/notation, you could write the same expression this way:

    
    
        { eat(food) : ∀ food ∈ { foods } ^ food ≠ "chocolate" }
    

You read that as "the set of eat(food) where for all food in the set of foods,
the food isn't chocolate". The notation will be quite familiar to
mathematicians, and thus if you have a strong mathematical background,
especially in set theory, discrete math, and combinatorics, the CoffeeScript
array comprehension feels natural.

See the Wikipedia article on Set-nuilder Notation/Set comprehension,
[http://en.wikipedia.org/wiki/Set_comprehension](http://en.wikipedia.org/wiki/Set_comprehension).

Here's another example from the Wikipedia article:

    
    
        { x | x ∈ R ^ x = x^2 }
    

This reads as "the set of all x, where x is a real number and x = x^2", which
evaluates to the set { 0, 1 }.

------
tomphoolery
I believe there will be a day when converting CoffeeScript to just native
JavaScript won't be very difficult, but until that time, it's useful as a way
to have neat syntax features without having to wait for browsers to support
it. Indeed, many of the features CoffeeScript introduced into the JS
developer's mindset are or will be present in the upcoming ECMAScript
specifications. We can only assume this trend will continue.

------
solox3

        delayed: () ->
          -> this.model  # isn't the class
    

Well, that isn't really fair now, is it? You could have used the fat arrow
(`=>`) for binding `this` to the class.

With that in mind, I agree with the author in that CoffeeScript isn't the
answer, at least not exactly. With syntax this incredibly similar, how far are
we from compiling python (with generators, with statements, imports, ...) to
JavaScript?

~~~
mistercow
>how far are we from compiling python

I frankly find CoffeeScript nicer than Python. There are advantages and
disadvantages, obviously, but whenever I'm writing Python, it makes me long
for CoffeeScript.

~~~
xixixao
Going from CoffeeScript to Python (bundled together with going from Node.js to
Python) is painful. So many things that CoffeeScript has learned over Python -
of all of them, "everything is an expression" rule.

------
rzimmerman
This is a bit overly critical. The implicit parentheses are optional, so if
it's confusing or ambiguous you should just use parentheses.

    
    
        func 5, {
           event: -> 45,
           val: 10}
    
    

Is reasonable but

    
    
        func 5, {
           event: (e) -> 
             if e.something
               36
             else
               45,
           val: 10}
    
    

Really ought to be split up for readability no matter what programming
language you use. And besides, the only issue is the extra comma causes it not
to compile.

To be fair, the `->` vs `=>` (which `this` is `this`?) for class members is
confusing. I'd almost prefer class members didn't give you the option and
defaulted to `=>`.

The "variable capture" section is overblown, though. You're a lot less likely
to run into this issue than the classic JavaScript "I forgot `var` and now my
variable is global.

My biggest complaint is actually the implicit returns. Sometimes I forget a
return statement but it works anyway because of this feature. Then I come back
later and modify the function slightly only to spend a bunch of time figuring
out why it's returning `undefined`.

~~~
jkrems
If you write JavaScript in strict mode the probability of incidentally
declaring something as global is pretty much zero. Those mistakes can also be
properly linted and warned against - which is not possible for CoffeeScript's
implicit declarations. And at least I had real-life situations where
CoffeeScript's scoping broke code in very subtly ways.

------
z3phyr
Then, for sure, Clojurescript is the answer.

~~~
aidenn0
Clojure is really hard for me to use, coming from a lisp background. The
various special forms seem to sometimes want a list and sometimes want a
vector and sometimes don't care. I've yet to find a way to keep track of that.

Anyone have a link to something from Rich mentioning why vectors are used in
basic syntactic constructs? It's the one departure from its lisp roots that I
couldn't figure out any motivation for.

~~~
mkremins
I've never seen any explanation from Rich on the subject, but semantically
speaking, vectors used in syntactic constructs are almost universally meant to
denote binding forms. Let-bindings, loop-bindings, function parameters and the
like all use vectors in the context of binding symbols to values.

I find that, having gotten used to the mental shortcut "square brackets ==
binding", the distinction makes it easier to read the "shape" of code from a
very high level and get a general understanding of its meaning at a glance.
YMMV.

------
slang800
The example in "Ambiguous Code" is ridiculous - if you write CoffeeScript like
that then you have much bigger problems. Also, the part in "Classes Are an
Illusion" totally fails to mention the fat arrow `=>`, which solves the main
issue the author raises.

However, this part I completely agree with:

> Realistically, the issues I have raised with CoffeeScript don’t come up
> every day. Ultimately though, they are enough to say we need something
> better. I hope to share some thoughts soon on what such a solution might
> look like.

CoffeeScript isn't perfect and we should always be looking for better
solutions. So I'm glad that the author wants to add to the discussion. While
CoffeeScript isn't _the_ answer, it's probably the best answer we have so far,

------
ritwikt
Coffee-script is awesome but suffers from it's roots as a preprocessed layer
on top .. and that essentially leads to poor overall tool chain support .. I
actually enjoyed writing code in it .. debugging not so much .. Would love
some of the constructs to make into JS

------
AdrianRossouw
I have a rule of thumb that coffeescript is never appropriate for code that
has to be require()'d by any code written by somebody else than me.

I'll happily use coffeescript, and enjoy doing so, when that condition is met.
It doesn't happen very often though.

------
mrcsparker
While it might not be the answer, it has been a very good answer for me.
Recently I worked on an Angular project that had a pretty complex data model,
and converting the model to CS made the code much more readable. The rest of
the app was still in JS, minus a ./models directory which was CS. The other
devs found the code very readable also.

I am biased towards Python and Ruby. I think that they are nice looking
languages.

Different tools for different jobs. Next time I am on a JS project and I want
to model data, I will probably use CS again.

------
timestep
Answer to what? What's wrong with Javascript in the first place?

~~~
jplur
For me, coffeescript was the answer to the question "How can I write
javascript with python-esque whitespace block formating?" I suspect the author
was asking something like "what can replace javascript?"

~~~
collyw
Coffeescript seems to be more like Perl, where parenthesis are often optional,
and meaning is implied by the context a lot of the time.

I like Perl, but I tended to be fairly pedantic with parenthesis and things
when writing it. I prefer explicit over implicit. (Though sometimes implicit
can save you a ton of time).

------
ryanatkn
The only gripe I share is scoping, and that's fixed in LiveScript. I've
started writing LiveScript in a fairly explicit style - for example I use
parentheses where they improve readability and I always use curly braces for
object literals. Qualitatively I think it's increased the readability of my
code way beyond JavaScript. It's nice to have curly braces carry specific
meaning instead of being littered all over the place.

------
anotherevan
CoffeeScript is putting lipstick on a pig. It's pretty damn good lipstick, but
still being applied to a pig.

------
aclimatt
My problem with CoffeeScript has always been the syntax vs. semantics issue.
CoffeeScript saw a big opportunity to improve JavaScript semantics and help
programmers more easily avoid the JavaScript minefield ("var" and "===" for
example), but in doing so decided "while we're at it, let's overhaul the
general syntax too".

Gratuitously changing "function" to "->" for no reason other than removing
characters seems to introduce more brand new idiosyncrasies than it's worth.
If the goal were to improve JavaScript as a language by smoothing over a few
of the gotchas, which of course would require a few syntax updates, then I
think it would be immensely valuable. (Think SCSS instead of the original
"Sass".) But it seems as if the authors were more troubled that JavaScript
didn't write like Ruby, so they made a new language that happens to compile to
JavaScript. And now I have two languages to choose from, each with pros and
cons and their own gotchas, adding more complexity to my decisions when I was
hoping for simplification.

~~~
andrewvc
I totally disagree regarding 'function'. Good javascript tends to be more
functional than imperative. That means using 'function' a lot. Most functional
languages use either fun, fn, or lambda, all relatively short words for this
because it's used ALL THE TIME.

Shortening it to two chars made sense IMHO. The long form of the word function
directly impacts code quality and readability.

------
mck-
These pitfalls can be easily avoided by following a styleguide [1]

[1] [https://github.com/polarmobile/coffeescript-style-
guide](https://github.com/polarmobile/coffeescript-style-guide)

------
jbeja
There is still not "answer", and the world is not gonna end tomorrow, in the
future maybe will be one but until that day comes i will stick with whatever i
find appealing to me at present. For now is CS.

------
h1karu
CLOJURESCRIPT IS THE ANSWER! no question about it

~~~
camus2
The problem I have with clojurescript is i couldnt find any closurescript
tutorial that did not involve java.

Let's say i want to start using closurescript,like coffeescript.

i want to do npm install -g closurescript then

closurescript compile myscript or closurescript myscript.

How do I do that?

If closurescript folks want their language to be popular with javascripters i
need to be able to do that.

Right now,searching on google,on npm, i did not find any tutorial that did not
involve maven or java.You cant expect a nodejs developper to learn maven or
install the JVM for the sake of using clojurescript.

coffeescript is popular because it's easy to get started with.You dont even
need to install anything,just add the coffeescript compiler to a HTML page.

~~~
h1karu
npm depends on a javascript compiler such as g8 so how is that different than
clojurescript depending on the JVM ?! It's no different at all you're just
complaining that you don't like to have to install software before using it
which is ridiculous if you want to use powerful software.

~~~
camus2
what is ridiculous is a compile to javascript language that is not written in
javascript itself.

------
oinksoft
Sometimes I think that most CoffeeScript, ClojureScript, etc. programmers are
people who were advanced in other languages before they learned JavaScript.
There are quite a few programmers who have no issues with these "bad parts" or
"really bad parts" because they cut their teeth on them, and these numbers are
growing: Most people now learn JavaScript as their first language. JavaScript
already won, and things like CoffeeScript are the last gasp of the old regime.

~~~
noir_lord
As someone from the old regime (cut my teeth on spectrum basic in the 80's,
get of my lawn etc etc) I sorta agree.

For years I avoided using javascript beyond wiring little bits of jQuery
together because I hated the language but eventually I ran into a project
where I could no longer do that and resolved to _learn_ javascript properly.

Many wtf's where had but now looking back I realise that Javascript is a warty
language (but then show me a widely used (top 10) language that _isn 't_).

I still don't like it but I don't hate it and I just accept it for what it is.

~~~
oinksoft
To an extent it is a Devil you know/Devil you don't thing. The moment one of
the JS-first people get bitten by the CoffeeScript compiler (having to
indent/dedent something, move a comma, suddenly your code is working ... I
think everybody runs into the sort of issues the author described) they are
going to go back to JS. JS is such a high-level language already, and the
browser vendors and SSJS projects seem focused on advancing it. I just don't
see much room in the future for languages like CS.

~~~
noir_lord
I agree the other issue with someone like me using CoffeeScript is that first
I'd want to _really understand_ Javascript otherwise I'd never be able to
trust that I could fix any bugs I ran across, it's another layer of
abstraction I essentially don't need.

------
igl
Livescript or Gorilla are what I would want from a .js precompiler.
Coffeescript just removes brackets and readability.

------
tsenkov
>I ... couldn’t figure out how to write the CoffeeScript for the JavaScript I
wanted.

------
hmans
What is the question?

------
jbeja
Who said it was?

------
teemo_cute
CoffeeScript seems to be an efficient alternative to plain Javascript. The
fact is you can't avoid seeing Javascript completely. Just try debugging in
Chrome or any other browsers built-in debugger and you'll know what I mean.

