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.
-- 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.
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= {}'
> 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.
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.
> I don't see that as a justification for limiting the expressiveness of a language.
That's a straw man. I never said that the expressiveness of the language should be limited. There are plenty of languages that are just as (more?) expressive than CoffeScript without the syntactical ambiguity.
> If you take that line of reasoning too far you end up with Java.
That's the slippery slope fallacy. I am in no way suggesting that CoffeScript should have completely rigid syntax. Surely there is a happy medium between CofeeScript and Java. There are plenty of languages that live there.
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.
Exactly. Expressiveness refers to the realm of problems a language can idiomatically address, not the number of ways a particular unit of logic can be equivalently written. If that were true, you could simply add any synonym for "if" ("when", "whenever", "assuming", "given" etc) to a language and claim the most "expressive" language.
Agree. When they invent a new language to fix some problems of the old one, if same problems (even more) appear in the new one, then why you need the new one? That's funny they try to fix some traps by introducing more pitfalls. What's the point? Those problems can be avoided by design, but they didn't.
In short, it was badly designed. Pointless to use it.
Also, his rebuttal doesn't defend the inclusion of those language features in the first place. If you simply "shouldn't" use a particular feature (e.g. if at the end of an expression), why should it be in the language at all? It shouldn't, ergo the language is nonsense, which was the original claim.
The last example I assigned the results to a var because it was doing a huge amount of work, any of the steps could fail, and it was just a lot clearer that way.
You don't always have to assign things to vars.
If you have two or more function calls on the same line, use parentheses after the first one. Or use parentheses in all of your function calls. Its just an advantage for some people to be able to leave the parens out because it is a little more readable for them. Otherwise, you can just write it the same as you would in JavaScript.
You had more than one example of pulling out "anonymous" objects from a call, because that is "how it's done." The point is that it is ridiculous that one must go to these lengths to help parse a language, especially when it flies in the face of the language's doctrine.
Same goes for parentheses "here or there but not there, sometimes." This may very well be the anathema for those that don't understand the claims that ";" or "function" or "}" are real burdens.
It doesn't go against the language's doctrine. The guy who invented it explicitly recommends pulling out anonymous objects and functions if they're not super trivial.
Exactly, CoffeeScript isn't an excuse for writing incomprehensible code.
To make the OP assessment of CoffeeScript fair we would have to apply the same logic to Javascript its self. If we looked at any minimised JS code we would have to conclude that the language is unreadable.
> Just because you CAN do something in CoffeeScript doesn't mean you SHOULD, or should ALL of the time.
In 1948, Edward Murphy, Jr. an aerospace engineer, was working for the Air Force to install sensors to test g-forces on humans during deceleration. There were two ways to wire each sensor, and one of them was wrong. Someone had methodically installed every single sensor backwards. Murphy quipped something -- no one is exactly sure what it was -- which was cited in the Aviation Mechanics Bulletin as "Murphy's Law: if an aircraft part can be installed incorrectly, someone will install it that way." A few mutations later and this became the famous "Murphy's Law".
I think the original Murphy's law applies with great force to the world of programming languages. If there are multiple ways of doing something, and some of them are stupid, you still have to know all of those stupid methods because some idiot on your team will do it. The probability of this happening increases as the size of your team increases.
The proper course of action as a language designer is to make sure that foolish methods are not built into your language. What you do not do is design foolish methods into your programming language, and then put up a big sign on Hacker News saying "don't do that".
The Original Murphy's Law is so critical to the design of systems -- languages, APIs, libraries, etc., that after your post I feel compelled to ask you to put down your Programmer's Card and step away from the keyboard at this time.
Right because programming is just like installing parts into an aircraft.
Since you are obviously an expert in programming language design, I am curious to know, what programming languages have you designed?
He made it flexible in order to appeal to people who want a functional programming style and like to be clever. I don't want to deal with that type of code especially but some people actually prefer that way if that is the way they have been programming for a number of years or if they are just looking for something new.
"Put down your programmer's card" -- very uncalled for.
Any language can be abused or used in styles that are difficult to read or maintain. Almost all languages that I have seen have more propensity for that than CoffeeScript.
This one of the best language designs ever because of the significant whitespace (which to me is logically the most obvious rebuttal to your comment), small amount of required punctuation, intuitive and practical keywords, solving many of JavaScript's problems, appeal to Ruby enthusiasts and functional programmers which represents a sizable chunk of the best software engineers in web development, and compatibility with JavaScript. In order to do all of that it needs to have the flexibility that we are discussing.
CoffeeScript allows for the closest thing to my pseudo-code that I have seen.
Anyway I have spent way too much time on this discussion already.
> Indentation is significant in CoffeeScript, just like it is in Python. Just having a parenthesis shouldn't change that.
Er... in Python, having a parenthesis does change that, within parens Python uses continuation lines which are not subject to the same restrictions as free-floating code.
wow thanks for writing this all out. i was going to tackle a few of the examples but it was going to take some time. my thoughts exactly. a lot of the examples no one would do and not even the coffeescript page documents it like so. some other people are right though in that there isn't any discouragement so far in writing things certain ways.
Usually I would write
or maybe If you write it the way he did, the parenthesis are confusing.For this one:
-- 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. Those are ridiculous examples. No one does that. You just write moveTo 10, 20, 10 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: and then I can just write You don't write it like that if the function takes two objects. You would probably just write 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.
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 !==. I'm not that sure about the use of unless, although it probably is a little bit more readable overall. 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: 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: I would never write something like 'mainModule.moduleCache and= {}'Instead of
I would write