
CoffeeScript: less typing, bad readability - dcu
http://ceronman.com/2012/09/17/coffeescript-less-typing-bad-readability/
======
jashkenas
Most of the bad code examples in this post are taken from the CoffeeScript
compiler itself. For that I have to say "mea culpa". There's a lot of overly
clever and dense bits that have accrued in the compiler over time -- sometimes
due to the tangly nature of the codebase, but also sometimes because we tend
to use the self-hosted compiler as a test bed for edge cases of combining
different language features together.

If you're looking for more regular style, this style guide is a better place
to start:

<https://github.com/polarmobile/coffeescript-style-guide>

~~~
lowboy
Perhaps a style guide should be put up at coffeescript.org, or at least linked
to.

~~~
WickyNilliams
I was literally coming here to post this response. It seems like a revolution
in (usage of) coffeescript is needed in much the same way Crockford's Good
Parts paved the way for writing good javascript.

Note: I'm not saying Crockford was singularly responsible for this, but The
Good Parts was certainly well-received and very much popularised for it's
opinionated views on the language.

Edit: I mean in terms of coding style, CS itself has already cut out a lot of
The Bad Parts of JS

------
crazygringo
This is a fantastic post -- I feel like I've run into all these crazy
"gotchas" over the past year, and more.

And the worst part of it is, nearly all the confusing/ambiguous/different
compilation examples given rely on the _undocumented_ rules CoffeeScript uses
for parsing. It's amazing that, still, CoffeeScript's entire documentation is
basically a "getting started" guide, and there is simply _no_ reference
documentation.

~~~
luriel
Magic overdose.

Compare with Go, where you can easily read the whole spec and keep the whole
language in your head: <http://golang.org/ref/spec>

~~~
deafbybeheading
Go is an excellent contrast. Not only is the syntax spartan, but--especially
if you include the built-in formatter gofmt--it has a fascist insistence on a
uniform coding style. I don't agree with all its stylistic decisions, but I'd
rather live with them and have consistency than run into corner cases and
gotchas.

------
smacktoward
I don't have a strong opinion on the article itself (it seems well-reasoned to
me, but I don't use CoffeeScript personally so who knows)... but the comments
attached to it are hilarious.

 _I think CoffeeScript has great readability, because I’ve taken the time to
learn how it works._

If you have to take the time to learn how to read something, it's not easily
readable.

 _CoffeeScript is only hard to read if you try to read it with a JavaScript
mindset._

Yes, why would anyone approach a tool pitched explicitly at JavaScript
developers, whose "golden rule" is "it's just JavaScript" (see the top of
<http://coffeescript.org/>), with a "JavaScript mindset"? Truly, it is a
mystery.

~~~
jaequery
i'll stick to javascript. coffeescript doesn't add a whole lot to the table,
javascript is the standard and that's a good thing, re-writing the language is
not the answer in my opinion. i'd have to imagine that saving a few keystroke
might sound sexy to lesser experienced developers, but that really is all it
adds to the table. being able to code on any project immediately off the bat
with a standardized language is a huge plus, in terms of flexibility and
scalability. you don't want to limit your company to exotic language, only to
later find out few months later another new language called "frapscript" is
now the new cool thing to do.

i recall the days when i was thrown into a project where the requirement was
to use mootools, rather than jquery. even though they are both "javascript" in
nature, it severely limited my productivity. i can see the same thing
happening to companies trying out coffeescript, it may seem like you are doing
the better thing long-term wise, but in reality, it is not so much. it's
better to just stick to standards and you'll be more productive down the line,
i can almost guarantee it.

~~~
encoderer
Your last paragraph confuses me.

So you had jQuery experience and were inhibited by working on a MooTools
project. I get that, makes total sense.

But then you say that switching to CoffeeScript may seem like a better _long
term_ choice but "in reality it is not so much."

Surely MooTools would've been fine for you _as a long term choice_.

Yes, there is a penalty to switching. Whether it's jQuery to MooTools, JS to
CS, whatever. But that doesn't make it a bad _long term_ choice.

Also, CoffeeScript is more than just saving keystrokes. That makes it seem
like it's all about initial up-front cost savings. Instead, it's about having
shorter, more expressive code. That pays dividends for the life of a project.

~~~
jaequery
"Instead, it's about having shorter, more expressive code."

yes, but at the expense of a lot of other negative baggages that comes along
with it. by having it's own compiler rather than leaving that to the browser
seems like it's opening a can of worms.

and just reading from the comments, i can see how we could soon see a birth of
"another language", that's supposed to be solve all problems coffeescript'ers
face.

for one, i guess readability seems to be the common problem, which isn't good
for productivity.

~~~
encoderer
It sounds like you haven't ever used CoffeeScript?

Don't you find it a little odd that you have such strong opinions on something
you've never even tried?

------
ricardobeat
Though most examples are not something you'd write normally, this line is what
kind of flopped the article for me:

    
    
        Given that CoffeeScript doesn’t fix any of the
        fundamental problems of JavaScript
    

same for a comment here:

    
    
        coffeescript doesn't bring much to table
    

There is _so much_ coffeescript adds that I find these laughable:

    
    
        string interpolation 
        multi-line strings
        comprehensions
        guarded loops (hasOwn...)
        easy constructor/prototype definition (class)
        avoiding global leaks/shadowing
        function binding
        splats, defaults
        safe usage of reserved names
        existential operator
        chained comparisons
        READABLE regular expressions
    

This just off the top of my head. These make a _huge_ difference to writing
code everyday. I've been writing CoffeeScript for 90% of my projects in the
past 2.5 years and it pretty clearly affected my productivity for the better.
I can only conclude that whoever says "coffeescript doesn't add anything"
hasn't really used it for work.

Case in point, if you look at the linked article at the end you'll see an
update by the author: _I actually love CoffeeScript now that I've been writing
it for a year_.

~~~
sktrdie
I totally agree that CoffeeScript brings a lot to the table compared to old
feature-less JavaScript. But the author is talking about readability of the
language, and not about the features that it has.

The problem that he points out about "Implicit is better than explicit" and
"There is more than one way to do it" are quite serious problems that modern
languages shouldn't have.

~~~
ricardobeat
See quote at the top, last paragraph from the post. His conclusion is that
these readability problems swamp everything that coffeescript has to offer,
which I think is really not the case - especially considering these are mostly
style issues.

------
tete
I don't consider this article bad at all, because it really makes some good
points.

However a lot of criticism seems to come from the fact that the author is a
Python programmer and therefor wants CoffeeScript to be more like Python. No,
I am not saying something like the author not understanding it isn't meant to
be Python, but for example the implicit vs explicit debate is certainly a more
philosophical view. Ask people who prefer other programming languages and they
will have a different view. Hey, after all that's why there are so many, even
if Ruby, Perl, Python, Falcon, etc. have very similar use cases.

My opinion for example is that dynamic languages are very implicit in first
place so saying you don't want that (at all) doesn't make too much sense. I
also don't have problems reading CoffeeScript, but occasionally had problems
with very explicit languages being too verbose which can make it harder to
follow. So looks like my mind works slightly different here.

But back to the article. There are lots of valid points. I think coding
guidelines, which one should have working in a team, no matter what language
could solve some of them. Some points look a bit like mixing different styles
on purpose and at least can't see how you could find something like that in
the wild. Just because you can code ugly, it doesn't mean you have to, but
again that is more of an opinion. Some people like usually verbose languages,
because they say they are easier to read, others like ones with shortcuts or
where you have multiple options to express things, making it easier to read
(for some people). I for example always enjoyed the fact that Perl has unless
and until in place of negated if/while.

But that's more what you prefer. But hey, CoffeeScript is all Javascript, so
if your team doesn't like it it's (comparatively) easy to step by step switch
back.

~~~
alecperkins
It's funny, because as a big fan of Python who has had to do a lot of
CoffeeScript lately, I find CoffeeScript very similar to Python, and very
readable. It's certainly more readable than JavaScript, when you don't get
fancy. It's called "Unfancy JavaScript" for a reason.

Many of the issues raised in this article can be solved by "simply" not doing
it (admittedly not always a real solution). Just because the language _allows_
something to be done, doesn't mean it _should_ be done that way. Our team has
a styleguide that clearly explains good and bad practice, for CoffeeScript AND
Python. (It's possible to do bonkers stuff in Python, too, just harder.) It
includes things like: use explicit returns, especially when intending to
return nothing; include parenthesis unless it's more clear without them
(callback as arguments).

Yes, it'd be great if the language were more explicit and made it harder to do
confusing thing. But, its core goal is being "just javascript", which prevents
some of that explicitness. Also, the flexibility lets the real goal be
clarity.

I find

    
    
        my_object =
            key: 'value'
            fn: (response) ->
                console.log(response)
    

to be more clear than

    
    
        my_object = {
            key: 'value',
            fn: function() {
                console.log(response)
            }
        }
    

because it doesn't have all the crap. CoffeeScript's whitespace syntax is even
more helpful when those objects start getting nested. Plus, not having to deal
with trailing commas is amazing. At the same time,

    
    
        someFn arg1, arg2, ->
            doStuffInACallback()
        , arg3
    

can be confusing, so parens help:

    
    
        someFn(arg1, arg2, ->
            doStuffInACallback()
        , arg3)
    
    

I try to not be "that guy" when it comes to CoffeeScript, but it's easily one
of my favorite languages now. All the crap that JavaScript requires is just
gone.

~~~
tjholowaychuk
both of those look really bad, try reading that sort of indentation when it's
already 4+ indentations in, it's terrible

~~~
alecperkins
I do every day, both in CoffeeScript and in Python. I find things like braces
frustrating, because I already keep it indented, and have to then manage the
openings and closings. With proper 'aesthetics', indentation is perfectly
readable. Plus, if something starts getting too indented than is readable,
it's a sign that it needs to be refactored. (Whereas JavaScript looks messy
even with otherwise sensible nesting.)

~~~
thezilch
Sorry, CS and Python treat whitespace as a significantly different beasts.
It's a disservice to everyone to say, "I read <insert significant-whitespace-
block language> everyday, therefore <insert language that substitutes anything
from call points, to auto-insert this or that, infer types, etc> is just
fine!"

I think a majority can grok and parse Python, but the same can certainly not
be said for CS. It's unfortunate too, because it has some Good Parts.

~~~
alecperkins
I didn't mean to say "Python does it, so CoffeeScript is not a problem", but
rather that _both_ can suffer from too much indentation. CoffeeScript is a
little more prone, given the callback-heavy nature of JavaScript, but similar
treatment of surrounding whitespace is helpful in maintaining clarity. (Basic
example: I find Python's standard of four-space indentation helps CoffeeScript
readability, and prefer it over the popular two-space indentation.) And in
both cases, excessive indentation is a useful signal.

Readability is very subjective and depends on the user's knowledge of the
language, as well as personal style, or 'accent', if you will. Code written
with, for example, leading commas in dictionaries instead of trailing commas
just looks bizarre to me and is a little harder to read, _to me_ , even though
I like to do something similar and stack colons.

------
crazygringo
Question: am I the only one who's driven nuts by "if"s that come _after_ the
"then" part? E.g.:

    
    
        do_something(with, these, args) if im_supposed_to
    

I mean, the processor/interpreter always needs to evaluate the "if" first, so
what purpose does it ever serve to put it _after_ the "then"? To me, it just
confuses things because it feels like code is getting executed backwards --
like crossing an intersection, and then checking to see if the light is green.

I know it works "in English" ("do this if that"), but when I scan other
people's code I'll sometimes completely miss the "if" (sometimes it's just off
the screen).

Are there any examples where this reverse-if actually helps, instead of
harming, code intelligibility?

~~~
OriginalSyn
I personally find that I end up reading more lines of code than I need to.

When scanning and I see

    
    
        If (condition) { perform_some_action(foo, bar, baz); }
    

And I know condition is false I can ignore what follows but

    
    
        perform_some_action foo, bar, baz if condition
    

I now have to stop and parse the entire line. But not only that, because it
can appear at the end I need to parse every line to make sure I don't get
caught by some if or unless. Short lines are easy sure but it's still annoying
to me.

~~~
ricardobeat
That would make sense if you were executing code in your head, but if you're
reading you want to read all of it anyway...

~~~
epidemian
But @OriginalSyn has a pont. If you are reading code because something is
misbehaving on a given configuration and you read

    
    
      if (some condition that doesn't hold on that configuration) ...
    

You can avoid everything inside that if statement if you know that's not
important for the case you're considering.

~~~
mayanksinghal
But if we want to avoid it, we would be required to already know what's inside
the parenthesis. If we already knew what's inside it, putting condition before
helps more as in that case (1) Either it's true and you have to parse the
block or (2) It's false and you just jump to the end of it.

------
cnp
Personally, i write my CoffeeScript with as much syntax as possible, to keep
it as readable as possible: as a rule, I always use parenthesis and commas
while leveraging CoffeeScript's "good parts".

But that said, the last couple of projects I've written in pure JavaScript and
it's actually made things much easier to go back and read. Like the author of
this post, I too have had difficulty reading back over my old code and, at a
glance, understanding precisely what's going on.

Over the past couple of months I've gone from being absolutely devoted to
CoffeeScript to on the fence, mostly due to readability.

(I'd love to see a fork of CoffeeScript that forces syntax.)

~~~
jotux
>I'd love to see a fork of CoffeeScript that forces syntax.

A compiler option that enforces syntax would be nice.

~~~
cnp
for what it's worth,
[https://github.com/michaelficarra/CoffeeScriptRedux/issues/4...](https://github.com/michaelficarra/CoffeeScriptRedux/issues/47)

------
cristianpascu
I have recently implemented to quite large project with CoffeeScript, the most
recent one for a full export to HTML for <http://flairbuilder.com>, and I have
to say that CoffeeScript is a superb language. It's a pleasure to work with.

The kind of problems that the article points out are easy to spot. If small
syntax changes yield significant output code, that will be immediately reflect
in the program execution.

Plus, a decent code base will have unit testing in place, which should catch
more intricate, harder to catch, unwanted code flavors.

~~~
streptomycin
> The kind of problems that the article points out are easy to spot. If small
> syntax changes yield significant output code, that will be immediately
> reflect in the program execution.

> Plus, a decent code base will have unit testing in place, which should catch
> more intricate, harder to catch, unwanted code flavors.

That's rather optimistic.

------
deanotron
I've been using coffeescript for about two years - I thought it was the best
way to keep the pleasant aesthetic of python, which was my favorite language,
and have been happy working with it ever since.

I just want to throw out a positive experience with it and to say that I don't
support the author's premise of "here's some misleading things you can do with
CS, therefore CS is unreadable". This applies to all languages, and 'fanciful'
features and syntax should be avoided almost always in every language for the
sake of readability.

There are MANY reasons not to use coffeescript, but JS is all functions all
the time, and -> is my best friend.

~~~
viseztrance
I haven't used CS as much as yourself, but I don't find anything pretty in
"element = =>".

~~~
deanotron
That is a good example, and something that is eased by syntax highlighting
(although I rarely implement double-bar function literals, keeping a pythonic
'self = this' reference is preferrable in most cases)

Although it is all subjective aesthetics, CS shines when paired with
underscore.js, and really all "callback-as-last-argument" paradigms, ie:

    
    
      _.each items, (item) ->
         # do stuff with item
         # ...
    

(edited formatting, also what alec said below :)

------
debacle
I find this review very even-handed. It doesn't really make any bold claims,
but it does provide a slew of evidence.

~~~
cheald
Eh. I think it's pretty silly. It basically boils down to "If you write
terrible Coffeescript, it's hard to read". Duh?

Any time you are writing code that is ambiguous, use what you need to in order
to clarify it. Don't omit punctuation just because you can if it makes the
code less readable.

    
    
       action(true, 
         option1: 1
         option2: 2
       )
    

Using empty parameters in a function declaration is even funnier; you're
adding punctuation that makes the code more vague. Just omit it!

    
    
       doSomething -> 'hello'
       doSomething(-> 'hello')
    

The third example is totally valid, and one I completely agree with - omitting
parentheses on inner nested function calls makes for unreadable code. Don't do
it.

The fourth example - complaining that inconsistent indentation produces
inconsistent results - is just incomprehensible to me. When you're using a
whitespace-delimited language, you'd best pay attention to your whitespace.

Ambiguities with optional curly braces are certainly nothing new to Ruby
developers. Convention is that only the last hash in an argument list may have
its braces omitted (or more stringently, a hash may only have its braces
omitted if it is the last parameter in the list). Makes for finely readable
code. Don't write unreadable code.

One of the fundamental rules you should follow when working in _any_ language
is "don't be clever". Optional parentheses can make for very clean code, but
if you try to get "clever" with them, you end up with ambiguous code. List
comprehensions are _awesome_ but if you use them when there's a simpler
construct you can use, you're doing it wrong.

You can write bad, unreadable code in any language. Part of maturation as a
developer is learning to write _readable_ code, not just working code. A bad
workman blames his tools.

~~~
njharman
> "If you write terrible Coffeescript, it's hard to read"

No, it's "If a language that provides for many ways to write terrible code
(incl many ways to write the same code), people will write hard to read code."
For example if parens are required, it is impossible to "get clever" with not
using them.

> A bad workman blames his tools

Great workmen evaluate and avoid bad tools.

~~~
masklinn
> No, it's "If a language that provides for many ways to write terrible code
> (incl many ways to write the same code), people will write hard to read
> code."

A prime historical example being Perl. A second one being PHP.

~~~
debacle
Perl is a great example because it is an amazing language with a horrible
reputation that it mostly deserves.

------
andrewingram
A few years ago I made an email campaign editor using JavaScript, I re-
implemented it in CoffeeScript a few months ago. What I now want to do is re-
implement it in the good JavaScript I've learned from reading the code that
CoffeeScript generates.

There are some annoying parts of CoffeeScript. If your function takes
callbacks as the first parameters, and another value as the second (such as
setTimeout), you end up with some really awkward syntax. I've seen a lot of
people define a delay method that swaps the parameters of setTimeout just so
it's easier to use with CoffeeScript.

Like the author of the article, I have a Python background, but I've also
written a lot of JavaScript, I _love_ the syntactic sugar that CoffeeScript
brings, but I hate reading CoffeeScript code. The project that my re-
implemented email editor is used in has a hybrid of JavaScript and
CoffeeScript code, and I'm not kidding when I say that everyone (myself
included) groans when they have to work on the CoffeeScript parts.

~~~
jashkenas

        > If your function takes callbacks as the first parameters, 
        > and another value as the second (such as setTimeout), 
        > you end up with some really awkward syntax.
    

Hopefully no more awkward than the equivalent call in JavaScript.

    
    
        setTimeout (-> alert "later"), 300
    

Versus:

    
    
        setTimeout(function(){ alert("later"); }, 300);
    

Or, on multiple lines:

    
    
        setTimeout(-> 
          alert "later"
        , 300)
    
        setTimeout(function(){ 
          alert("later"); 
        }, 300);

~~~
andrewingram
But here we're introducing brackets just to avoid the syntax ambiguity. The
Pythonista in me is crying out for a single way of doing things, either
require brackets or don't. It makes me want to go down the road of always
using parenthesis in CoffeeScript, but then it'll feel like I'm not using the
language in an idiomatic way (which is something I hate doing).

~~~
noonat
In my mind, this usage of parenthesis is less ambiguous. Parenthesis are used
in C-like languages for both function calls and order of operations. That is
to say, they are used in these two ways:

    
    
        foo(a, b, c)  // functions
        (a + b) * c   // order of operations
    

Making parenthesis optional for function calls means parenthesis are used
instead for just controlling order of operations.

In practice, CoffeeScript can't always guess when something is a function call
(such as a function call without arguments), so you end up mixing in some
function call usage no matter what.

~~~
lttlrck
I really hope it isn't guessing anything...

------
ryankshaw
whenever I see something like this that tries to rag on coffeescript it seems
like they all reference ryan florence's post from a while ago:
<http://ryanflorence.com/2011/case-against-coffeescript/>

for the sake of clarification, ryan is sitting right next to me, writing
coffeescript (as with all new code we write here at instructure, see:
[https://github.com/instructure/canvas-
lms/tree/stable/app/co...](https://github.com/instructure/canvas-
lms/tree/stable/app/coffeescripts) )--and loving it. whatever "crazy gotchas"
he found back then are obviously trivial to how much easier coffeescript makes
life. it seems like every third tweet he makes is about how much he loves CS
now: <https://twitter.com/ryanflorence>

Other than that, everything in this post just comes down to "just because you
can doesn't mean you have to or should." disambiguate if helps make things
readable

~~~
jashkenas
Perhaps it's time for Ryan to write that follow-up post ;)

------
eranation
I guess I'm lonely in this world, but I really want a statically typed
JavaScript alternative. Dart is nice, but no JS interop (yet), GWT is just
Java, which is not the most fun thing in the world, ClojureScript is nice, but
not static typed and Lisp is a bit too extreme for me, but the new Scala JS
DSL seems worth waiting for.

~~~
ebiester
<http://haxe.org/>

I would say ActionScript, but FalconJS hasn't been released yet. There are
other projects (such as roy) that are more functional in nature as well.

~~~
eranation
I have to try Haxe, but I can't help but wonder, it's been around for a while,
how come it didn't get more traction? I assume I'll have to try and find out.

I was a flash developer way back (2003), I hear you.

------
gothy
Using CS for about 1.5 years now. Yes, there're ways to hurt yourself with bad
CS code. This is also true for Python.

When developer writes some fancy one-liner in CS or Python and I'm reviewing
his commit, I just ask him to come over and explain what this thing is doing.
Sometimes it takes more than 20 second to read and explain even by author.
Then I say: "You wrote this line an hour ago and it's already hard for you to
understand what it does. Imagine you'll need to change it in a month. You'll
hate yourself. Go and rewrite this code explicitly to help yourself in the
future."

If you force yourself and teammates to write explicit code, you get all the
pluses of CoffeeScript avoiding bad readability.

------
armored_mammal
I concur with the author. When I write CoffeeScript I often use a more
explicit or more c-like style for things I find ridiculously ambiguous or hard
to parse when reading quickly.

Particularly, if one line has lots of commas, I put parens all over the place
because no matter what I do, having to manually parse the comma arrangements
and figure out what's nested and what's a function does not go quickly. I also
find myself writing explicit returns somewhat frequently just so it's much
more clear what's being returned.

The overarching issue is that the syntax blurs rather than pops -- there are
too many instances where things that are significantly different in function
look nearly the same.

------
ilaksh
Just because you CAN do something in CoffeeScript doesn't mean you SHOULD, or
should ALL of the time. Just like in JavaScript where, if you want, you can
write all of your code on one line, but you shouldn't.

    
    
        action true
          option1: 1
          option2: 2
    

If you really use CoffeeScript regularly, that isn't confusing. I don't
usually write it that way though. I would do this:

    
    
      options =
        a: 1
        b: 2
      action true, options
    

doSomething () -> 'hello' just isn't valid code.

Usually I would write

    
    
        doSomething ->
          return 'hello'
    

or maybe

    
    
        doSomething -> 'hello'
    

If you write it the way he did, the parenthesis are confusing.

For this one:

    
    
        action = (token, i) ->
            @tokens.splice i, 0, @generate 'CALL_END', ')', token[2]
    

\-- first of all, you always want to indent two spaces. But the main problem
with that is in CoffeeScript you do need to use parenthesis after the first
call because your code will be unreadable otherwise. You just can't write it
the way he did.

    
    
        moveTo 10,
          20
          10
    
        doSomething 1,
        2
        3
        4
    
        doSomething 1,
          2
            3
           4
    

Those are ridiculous examples. No one does that. You just write moveTo 10, 20,
10

    
    
        doSomething (->
        'hello'), 1
    

Indentation is significant in CoffeeScript, just like it is in Python. Just
having a parenthesis shouldn't change that. Anyway, what I do is this:

    
    
        somethingDo = (ms, func) ->
          doSomething func, ms
    

and then I can just write

    
    
        somethingDo 1, ->
          'hello'
    
    
    
        action(key: value, option: value, otherValue)
    

You don't write it like that if the function takes two objects. You would
probably just write

    
    
        action {key: value}, {option: value}, otherValue
    
    
        x = {
          key1
          key2
          key3: value3
        }
    

This is called destructuring assignment, and its part of the new ECMAScript.
Its useful to not have to repeat key1, key2 everywhere when the variable with
the value has the same name as the object property. The extra curly braces are
just necessary to differentiate from the normal syntax.

Sometimes yes/no or on/off are more readable than true/false. That's an
advantage.

    
    
        x = 1 if y != 0;
    

Don't use semicolons in CoffeeScript. I also don't put if statements at the
end of a line because I don't believe that is very readable for most people
including me. Also, in CoffeeScript its probably better to use isnt instead of
!=, although rather than !=, you would want !==.

    
    
        if y isnt 0
          x = 1
    

I'm not that sure about the use of unless, although it probably is a little
bit more readable overall.

    
    
      break for [tag], i in @tokens when tag isnt 'TERMINATOR'
      @tokens.splice 0, i if i
    

He says that is supposed to delete TERMINATOR from tokens. I tested it, it
doesn't do anything, and the second example of the correct way doesn't work
either. I think he meant this:

    
    
        filtered = []
        for token, i in tokens
          if not (i is 0 and token is 'TERMINATOR')
            filtered.push token
    
    
        i += block.call this, token, i, tokens while token = tokens[i]
    

Another example of something you CAN do in CoffeeScript but shouldn't.
Actually it is a bad idea in general. I think a CoffeeScript programmer would
actually write something like this:

    
    
        class Parser      
          block: (token) =>         
            @currentNode.push new Token(token)
          parse: =>
            for token in tokens
              @block token
            

I would never write something like 'mainModule.moduleCache and= {}'

Instead of

    
    
        js = (parser.parse lexer.tokenize code).compile options
    

I would write

    
    
        tokens = lexer.tokenize code
        parsed = parser.parse tokens
        js = parsed.compile options

~~~
joemoon
> Just because you CAN do something in CoffeeScript doesn't mean you SHOULD,
> or should ALL of the time. Just like in JavaScript where, if you want, you
> can write all of your code on one line, but you shouldn't.

Isn't this precisely the problem? Why make a better Javascript then make the
same mistakes as the original? One of the main goals is for Coffeescript to be
more readable that Javascript. Having ambiguous syntax and so many different
ways of doing things means that people will write code in all of these
different ways.

Your rebuttal is a long list of what you SHOULD and SHOULDN'T do, but there
are two problems:

1\. Not everyone will agree with you.

2\. People will write it the "bad" way anyway.

Ultimately this means less readable code, especially when you have to read
someone else's code.

~~~
Contero
> 2\. People will write it the "bad" way anyway.

People will write bad code in every programming language you give them. I
don't see that as a justification for limiting the expressiveness of a
language. If you take that line of reasoning too far you end up with Java.

~~~
lmm
Or python, which is where the author is coming from. In python there are fewer
syntactic ways to write the same thing (semicolons aren't optional, they're
just not permitted. The only ways to write and and or are 'and' and 'or', '&&'
and '||' simply don't exist. Map literals always look like {key1: value1,
key2: value2}, the braces are non-optional ).

Even python's critics would admit it's a very readable language, and it would
be unusual to claim it's not expressive.

~~~
jmmcd
A nitpick: you can use semicolons in Python.

    
    
        x = 3;

------
sixbrx
I haven't programmed in Coffeescript, but does it bother anyone else that new
variables are introduced without "var"?

When reading js, seeing the "var" really helps me to know the programmer's
intent that this is a new variable being introduced, not an attempt to
reassign one that should already exist. Does CS have features that make this
point mute?

~~~
mcmire
This doesn't bother me at all. Mostly because this feature comes from Ruby and
so I'm already used to it, but also because it takes away the nasty surprise
that JavaScript gives you if you leave 'var' out. I find this invaluable. As
for knowing whether or not a new variable is being declared, well, that's why
you keep your functions (and therefore your scopes) short.

~~~
masklinn
> This doesn't bother me at all. Mostly because this feature comes from Ruby
> and so I'm already used to it

This and that are completely orthogonal though, I've been using Python for 8
years and Ruby for 6 so I'm used to implicit scoping. Doesn't mean I like it,
or find it a good idea to use it in new languages (I don't).

And the issue is actually bigger in coffeescript than in ruby and python both,
interestingly because (through javascript) coffeescript's scoping is much more
regular than Python's or Ruby's.

The only language in which I don't know implicit scoping to be an issue is
Erlang, because it uses bind-once and immutable structure semantics.

> also because it takes away the nasty surprise that JavaScript gives you if
> you leave 'var' out.

That can trivially be fixed by linting, or using strict mode. That's really no
argument.

------
TeeWEE
The big point here: less characters for the same logic is not always better.
Saying that you need less characters to write function x in coffeescript
compared to javascript doesnt mean it is better.

Its all about syntax and semantics. Code from languages with a small and
consistent syntax, one-way-to-do-it, and a easy semantics are easier to
understand than languages with a lot of semantics.

For example, Scala is cool. But also overly complex. The same holds for C++.
But languages like clojure are very simple to grasp and the semantics of these
languages are very small.

------
mratzloff

        Coming from Python [...]
        
        For example, in C-like languages, you can omit curly brackets 
        after a conditional expression if you only have one statement:
        
          if (condition)
              action();
        
        But what happens if we add a new statement:
        
          if (condition)
              action();
              action2();
    

Of course, that doesn't seem to be an issue in Python, the language he's
coming from.

Most of his points are similarly contrived and could be equally applied to
Ruby, a language which doesn't require parentheses and quite a lot of
developers seem to like, or Python which is similarly whitespace-dependent and
quite a lot of developers also seem to like. But inflammatory headlines do
drive traffic from HN...

    
    
        Given that CoffeeScript doesn’t fix any of the fundamental problems of JavaScript
    

I think most developers who are well-versed with both JavaScript and
CoffeeScript would disagree that CoffeeScript doesn't fix any of the problems
with JavaScript. It certainly makes it easier to loop through object
properties. It makes code more readable in a number of ways; post conditions,
list comprehension-like syntax, simpler loops, the existential operator
(`foo?`), and the maybe object-like syntax (`foo.bar?.baz?.quux`) are
definitely improvements.

You can of course write bad code in any language, no matter how structured it
is. I myself am about to embark on refactoring a massive, _terribly_
-constructed Python system that processes millions of requests each day. The
author didn't follow the strictures of the Python community at all. How is
that any different from someone who exercises poor judgment when writing
CoffeeScript? It's not.

~~~
Macha
The issue with the optional curly brackets is that for new users, or even
experienced users reading through code quickly is that at first glance:

    
    
        if(something) 
          doSomething();
    
    

And:

    
    
        if(something) 
            doOneThing();
            doAnotherThing();
    

Both look like they should execute the same way - running the indented code if
the condition is true. The reason this is a problem in C and not in python is
that in python, this code operates as it intuitively looks, while in C, it
does not.

(It can trip up experienced users if they're not paying enough attention and
their mind just assumes the curly brackets are there.)

~~~
artsrc
The issue is that:

    
    
      * Humans use indentation
    
      * The Compiler ignores indentation
    
      * The indentation and the the compilers interpretation are different

------
tharris0101
This is exactly why I stopped using CoffeeScript. I hate Javascript so I was
excited when I saw CS for the first time but after a while I realized I was
doing two calculations in my head:

1: What is the JS that CS was generating?

2: What is the JS doing?

Maybe I just didn't give it enough time, but it seemed quicker and more
reliable for me to just suffer through the JS syntax.

------
mcantor
_Both statements do completely different different things, although they look
very similar._

This is true for both CoffeeScript examples he gave and their resulting
JavaScript.

------
latchkey
I agree, it is too bad that CS has so many optional ways of doing things. That
said, it is possible to write unreadable code in pretty much any language. If
you have a good style guide and stick to it, it is easy to avoid all of these
issues.

------
tjholowaychuk
Great article, totally nails it. No "good" language design should be so
ambiguous

------
ojosilva
After reading this, I felt the urge to classify key aspects of write and
readability of the programming languages I've dealt with over the years.

How easy or fast it is...

    
    
      - to write what I want to achieve
      - to write something that makes me feel creative
      - to write something that makes me feel tidy, organized
      - to write a syntax error
      - to write a logical error
      - to step into a "gotcha"
      - to find that bug
      - to grasp a short snipped
      - to grasp a 20K loc app
      - to read my own code 1 week later
      - to read my own code 3 years later
      - to read somebody else's code
    

Now trying to rate languages by these parameters is a tough job that I can't
even imagine how to tackle. In many instances it doesn't even has to do with
the language itself, but rather with my experience and relationship with it.
But any exercise in this direction gives some food for thought while trying to
find the right tool for the next job. Or something to think about when looking
back at some of the choices I've made through my programming lifetime.

~~~
orangecat
_\- to grasp a 20K loc app_

Although, 20k lines of Python is probably doing much more than 20k lines of
Java.

------
tylerlh
Yeah, well that's just, like, your opinion, man. -- The Dude.

Personally, CoffeeScript has been my favorite thing to come about in the past
few years.

------
jtms
CoffeeScript readability > Javascript readability

and that's all that matters to me

~~~
lmm
But the whole point of the article was that that isn't true, because
CoffeeScript makes more things optional (e.g. in Javascript if you don't see
brackets then you know it's not a function)

~~~
jtms
Yeah that's obvious, but I disagree with "the whole point of the article"
hence my previous statement.

------
d0m
Thanks for this post. This is actually how I feel about CS but could never
actually explain it correctly. I find it very hard to read other people code
because of all these implicit rules that are more often than not ambiguous.
Yes, sometime it's _shorter_ but not necessarily _faster_ or _easier_ to read.

------
iamwil
Some of the complaints in the OP aren't mistakes that I make often, so I guess
I don't see them. Perhaps for someone that makes those types of mistakes
often, it'd be a detriment, but so far, I've been happy with my coffeescript
experience.

------
viseztrance
The moment you try to do simple things like concatenating a string you realise
that javascript is a bit more tedious than it needs to be.

While nowadays I prefer coffeescript to js, I would rather have some syntactic
sugar like scss is for css. I've looked into it but nothing has enough
momentum to make me sure it will still be around in two years or so.

As a sidenote, while I mentioned I prefer CS, have you ever tried using a
ternary operator? or pass a callback function in jquery (ex. the hover out
event)? or just return "this". There are so many things that feel so wrong.

~~~
svachalek
Feel so wrong in... CoffeeScript? Or JavaScript? I think ternaries and
callbacks are both much cleaner in CS (with the exception of "callback,
something-else" which does end up a little funky unless you add parens). Just
naming a variable to return it seems a little wrong to me but you can always
leave the "return" in. "Optional" is very different than "never use".

~~~
viseztrance
Those last things feel wrong in coffeescript. Honestly, what's more readable:

    
    
      x = a ? b : c
    

or

    
    
      x = if a then b else c
    

And for the last one:

    
    
      function() {
        // doing something
        return this;
      }
    
      ->
        # doing something
        @
    

Don't get me wrong, I love the fact that I can do nice stuff such as
callback?() and some other nifty tricks, but while I'm still having fun using
coffeescript, in my experience it's not that great as most people make it up
to be.

~~~
jashkenas
Just FYI, using standalone `@` isn't considered to be good CoffeeScript style.
It's discouraged for this very reason -- just use `this` instead.

The reason why it works in the first place is for consistency ... in every
other context, you can use an `@` to replace a `this` or `this.`.

~~~
viseztrance
FYI, I usually use this instead of @ myself, but in this case I used @ to
empathize a grander issue.

And it's not like there's a warning about it being removed on coffeescript.org
where it's being mentioned as an alias for this in the first place.

------
jaysoo
I myself enjoy using CoffeeScript, but I understand it might not be for
everyone.

It's always good to look at the pro/cons before choosing a language, so I
think discussions like this is good.

That being said, some of the problems this article points out can be addressed
by going back to more JS style.

e.g. Not relying on implicit parentheses/commas/braces

I like the "Fancy" for loop because it's closer to what I do in Python (yes I
know they are not exactly the same). Same thing with the "Tricky" if
statements.

Also the redefinition shortcuts provided in CoffeeScript is pretty much what I
do in plain JS anyway.

e.g.

JS: foo = foo || 'bar';

CS:

    
    
      foo or= 'bar'

~~~
pistoriusp
CS 1.3.1:

"Conditional assignment of previously undefined variables a or= b is now
considered a syntax error."

~~~
jaysoo
Yeah I know. It was just a quick example.

It's useful for something like:

    
    
      f = (options) ->
        options.foo or= 'bar'
        # ...

------
endemic
Here's my own anecdotal example of CoffeeScript's readability.

Once, before banging out a bit of complex code, I thought I'd write out some
psuedocode to help wrap my mind around what I wanted to do. I type out my
psuedocode algorithm, realize I've written valid CoffeeScript, then uncomment
it.

That's the experience that made me think CoffeeScript is MORE readable than
JavaScript.

------
rayiner
I'm meh on significant indentation, but significant space characters is just a
terrible idea. I blame Haskell.

------
losvedir
ParenthesEs is the plural, parenthesIs is the singular.

Normally I don't do the spelling/grammar thing, but it was consistently wrong
in the article, and at least a half dozen comments here were getting it wrong,
too, so I figured a public service announcement was in order.

------
dustingetz
wow readability is about API design like requests vs urllib2:
<https://gist.github.com/973705>

except when APIs get 100x bigger, API design becomes 100x more important. and
using a language ecosystem that encourages good API design, over a language
that is cobbled together and has no particular opinions about what good API
design looks like[1] (or, even, bad opinions[2]), so that less experienced
developers end up with decent output, is that much more important than
concerns like parens, commas and braces. curly braces never made a project
fail. shitty API design does.

[1] javascript! [2] java!

sheesh. there are bad things about coffeescript, but this stuff hardly
matters.

------
tiglionabbit
Oh dude, just learned something new from this article. options = { a b c }
generates options = { a:a, b:b, c:c, } I have a lot of maps in my app that
look just like that. It'll save me a lot of repetition.

~~~
j-kidd
May I ask what are the use cases for maps like that? I don't think I have ever
needed one myself.

~~~
lowboy
I have situations like this quite frequently where I need to turn vars into
members of an object:

    
    
        title = getTheTitle()
        img = (shouldWeGetImg) ? getImg() : "placeholder.jpg"
        body = ...
            # 8 lines of code to define body, some that reference title and img
    
        # this:
        obj = { title, img, body }
    
        # instead of:
        obj = {title: title, body: body, img: img}

------
kin
while the points in the article make sense and I agree, if you keep your
Coffeescript code consistent I really don't suffer a readability problem,
especially relative to JS where there's like 5x more code to go through

~~~
kzahel
That's an unfair hyperbole. CS saves you at most ~30% characters, and that's
when omitting every parenthesis possible.

I personally don't get excited by that prospect. Generators would get me
excited, though!

~~~
kin
well, personally when i converted over i never had to stare at these blocks
anymore: } } } });

made code a lot easier to debug. and yes, consistency wasn't the only thing. i
would say that converting over has a learning curve sure reading other
people's code. but sacrificing readability long term compared to vanilla js? i
wouldn't say that. i'm not saying there isn't ambiguity in the beginning but
eventually you learn how to not do things in ambiguous ways.

------
gbin
I had this same feeling programming in ruby few years ago when no formal
language grammar was defined (with really weird problems with : vs [space]:
AFAIR). Is it the same for CS ?

------
systems
on one of the slide in this presentation i found this interesting (
[https://speakerdeck.com/u/clkao/p/livescript-tax-free-
javasc...](https://speakerdeck.com/u/clkao/p/livescript-tax-free-javascript) )

    
    
       Javascritp + ruby  = coffeescript
       coffescript + perl = coco
       coco + haskell     = livescript
    

So i think coffeescript is not the end of the line, and i think this mean,
there is a serious need for a better javascript

------
beernutz
Badly written code is badly written code in ANY language.

------
paulbjensen
I wrote Dashku entirely in CoffeeScript. It was a productivity boost, and for
that I owe it my firstborn child.

------
rimantas
Seems like there are two types of developers: those who don't want even to
hear about CoffeeScript and trying hard to find deficiencies in it and those
who embraced it and feel unhappy every time they are forced to work with
vanilla javascript again.

~~~
jlongster
Or, there are different opinions on how things work, each finding their
language superior in writability and readability.

There are no absolutes. This is all subjective.

------
lucian303
"readability is more important than writability for a programming language"

Couldn't agree with you more. Readability is measurable and considering that a
lot of programmers come from C-type languages, I really don't see why people
try to modify an existing formula (as badly implemented as that formula is in
JS).

tl;dr: Let's face it, if you're using Coffeescript or similar because there
are too many braces or parenthesis, perhaps you should quit development right
now and take a class on basic algebra, quit that and save the world your
horrific code. Seriously.

~~~
klibertp
Readability is measurable, that's true, but the second part of your sentence
makes me wonder if you really understand what readability is.

Do not confuse readability with familiarity. Also, don't forget that
readability is a function of __both __syntax and semantics.

Also, I really don't know what connection there could be between aesthetic
preference and quality of code produced. Are you aware of some study that show
that kind of connection? With conclusion which says that if I like line noise
then I am a great programmer, and if I like whitespace I am bad? If not then
your 'tl;dr' is just stupid, sorry.

~~~
lucian303
This isn't about aesthetics, it's about grammar. Just as in written human
languages, computer languages have grammar that make things easier to read and
understand. How well that grammar is done depends on the language. My point is
that if aesthetics is one of the reasons you choose a language, you really
don't understand software development or the simple idea of "use the right
tool for the right job."

~~~
orangecat
_My point is that if aesthetics is one of the reasons you choose a language,
you really don't understand software development_

Some would disagree: <http://paulgraham.com/pypar.html>

