Not sure why it needs the sensationalist title if the author's underlying point is simply that Coffeescript is a pretty good tool for writing nicely patterned Javascript and not a language in and of itself. I guess it is a marketing ploy. I expect it will work.
I usually write these sort of titles because they amuse me rather than in the extreme hope of linkbaiting. I accept that writing for my own amusement has about as much value for others as laughing at my own jokes.
It is a bit of a bait and switch, you don't let people know that you think it is a "damn good tool" until towards the end. I'm ultimately neutral on this. It sort of works to keep your audience engaged with your writing, but is a bit of a cheap trick to not put all your cards on the table until the end of the article.
Oh, and when you are writing you are almost always writing for an audience -- esp. when you tweet the result right afterwards and show up on Hacker News to discuss it.
I see that in addition to choosing a title that displeased you, in responding to you I failed to make it obvious that I agreed with you somewhat. I didn’t say I don’t write for an audience, I said that I selected the title for my own amusement, and that it would be better in some ways to refrain from enjoying my own little joke.
For what it's worth, I saw the title on HN, then saw that it was a link to your githublogthing and guessed "aw, he's going to be cheeky and turn it around in the post by interpreting it literally." So I thought the title was clever.
I like the title. It's based on a quote. I think it will get people to read it, sure, but it will also get people to remember it, as well as the Perlis quote. It's also fun to guess what the contents of the article will be. Partly because I knew raganwald liked CoffeeScript all right, I solved that riddle before reading it.
I'm not particularly sold on CoffeeScript, however this article seems to imply we'll someday have to maintain the generated files? As long as you keep the source near the generated files (which should be easy with version control -- you shouldn't even be checking in the generated source, in my opinion), I don't see the problem.
I'm somewhat unsure of the long term cost to benefit ratio of using Coffeescript. You are basically getting some syntactic sugar in exchange for the cost of learning new syntax and complicating your build and debug procedures.
I'm trying coffee on a relatively small project with only a few developers. So far I'm happy with the tradeoff. I keep my Coffeescript simple so the Javascript is almost exactly what I would write by hand.
Agreed, I usually .gitignore the generated JavaScript. Though sometimes it is useful to also provide JS in the repository, so people checking out the repo can immediately have running examples.
In spoken languages, there is a difference between a language, a dialect, and a specialized vocabulary. My premise is that CoffeeScript is a jargon of JavaScript. Maybe you could say it’s a dialect of JavaScript. But my premise is that notation alone does not make it a distinct language.
I can’t speak to whatever C looks like today, but when I first learned it, absolutely positively C was a kind of portable dialect of assembly for an idealized CPU architecture.
For example, the (in)famous equivalence between 10[p] and p[10] point to C being a kind of translator rather than an entirely new way to think about programs.
I'm curious if your opinion on this would change if they made it so the browser could run Coffescript natively. Personally, I think the fact that it compiles to an intermediate language to be irrelevant to whether Coffeescript should be considered a language.
I consider it a different language if for no other reason than, if a programmer familiar only with Javascript looked at code written in Coffeescript, they would not understand it at all. And it can't be converted to Javascript without either considerable hand work, or via an automated tool.
If this “running natively in the browser” did not involve 100% cross-compatibility with existing JavaScript code, you might be moving up from jargon to a dialect.
But as long as the underlying model is the same, and as long as it’s a leaky abstraction, I don’t think of it as a separate language.
For example, if it were to be a separate language I would look for its OOP stuff to be implemented in the “engine” and not to be strongly related to the JavaScript prototype mechanism.
Surely it's much more like a grammar than a jargon, since the content essentially stays the same (symbol names, values, etc.) but the arrangements change.
In general, langages don't tend to have multiple grammars (although spoke languages tend to be looser than written), and perhaps the unnaturalness of having a second grammar might undermine your position.
The intrinsic quirks and behavior of CoffeeScript and JavaScript are the same. You cannot think of CoffeeScript as a kind of Python. It's a better (but with caveats) syntax for JavaScript.
There's a 1-1 mapping of CoffeeScript syntax to JavaScript syntax. This is really useful when you are debugging. But it cannot introduce much useful new behavior.
That's why I'd agree its more appropriate to see CoffeeScript as a new syntax for JavaScript, than as a new programming language.
> Ryan Florence argues that if people use CoffeeScript to write JavaScript programs, maintenance will be a nightmare:
I posted that article a little prematurely and more as a rant for my co-workers. It was a bit misunderstood (and it blew up online before I even knew it so I didn't bother editing).
My point in that quote was that bad CoffeeScript is worse than bad JavaScript.
syntax doesn't make code beautiful, you can trust me on that one. I've seen beautiful C, lisp, erlang, js, asm, you name it. IMO the fanboy-ish nature of CS just screams naivety to me, kinda like when Ruby people think its syntax is "amazing", they all suck just in different ways :D haha if anything lisp is probably conceptually the most elegant
True, you can find ugly parts anywhere if you look hard enough. This however does not make everything the same. There is a huge difference if you encounter ugliness in every line you write or just in obscure cases. Syntax does matter.
I find really well-written CoffeeScript easier to comprehend and scan, even though the community at large believes I hate the stuff entirely (I don't).
I'm just not sure if it's enough to make up for a less-than-optimal debugging experience, especially considering that most of us don't write really excellent code all the time.
> You don't "Think in CoffeeScript," you "Think in JavaScript." Only you think in well-crafted JavaScript.
Not true, if only because CoffeeScript includes classes as a language feature. In JavaScript it is a hack. This might change with EmcaScript.next, but for now that creates a significantly different way to design your code.
Try writing a Batman.js app in JavaScript and you'll see what I mean. With await/defer possibly being merged into CS, we're going to see the languages diverge further in the future.
You missed the rest of the essay, wherein Raganwald described how CoffeeScript “features” are a shorthand for common JavaScript design patterns, forcing everyone to use the same patterns in the same way. [In other words, he answered your specific comment at great length, rendering your criticism of one out-of-context quotation a bit weak, eh?]
Specifically, most major JavaScript projects have some kind of class implementation which makes inheritance, creating new classes, &c. easier. Some of these are quite elegant, but they end up being annoying anyway, because each system is slightly different. CoffeeScript takes one particular pattern (which is thankfully compatible with the expectations of Google's Closure compiler) and gives it a shorthand, so that everyone writing CS code will be on the same page.
Class inheritance is not a common JavaScript design pattern. It's a hack, used by a minority of JavaScript developers, in a minority of projects.
The crux of the argument is that when you write CoffeeScript you think in JavaScript. But I absolutely never think about overriding a parent function in JavaScript. In CoffeeScript this is actively encouraged.
Like I said, as other ideas like await/defer become more mature (and are merged into mainline), we're going to see the design patterns diverge futher.
> But I absolutely never think about overriding a parent function
> in JavaScript. In CoffeeScript this is actively encouraged.
Unfortunately, if you never think about overriding a parent's implementation of a function in JavaScript -- all that means is that you willfully don't use prototypes. The famous "prototype chain", by which object-orientation in JavaScript is accomplished, is all about overriding versions of parent properties.
> Class inheritance is not a common JavaScript design pattern.
> It's a hack, used by a minority of JavaScript developers,
> in a minority of projects.
Nope, it's deeply ingrained in all object-oriented JavaScript that uses prototypes. What are the built-in String, Function, RegExp, Number, Array, and Object, if not classes?
There are a half a dozen different implementations of class inheritance in JavaScript. However no one writing a JS library is going to ask the consumer to extend one of their objects. This is what inheritance is all about. In Java you extend everything. Backbone.js is the only popular JS library I can think of which has their users use this pattern. It doesn't make since most of the time because:
1) The use of the pattern is not common in the js community.
2) If someone does use the pattern, they might be using a different implementation.
That you can override an Object's toString is not what we're talking about here jashkenas. We're talking about creating an Animal class and extending it with Horse.
> However no one writing a JS library is going to ask the consumer to extend one of their objects.
Uh, if you're using the Closure libraries, you very likely are extending goog.Control or goog.Component. I don't know dojo, but from my brief perusal of the docs it looks like you do the same thing with dojo.declare. YUI seems to do the same with Widget. I'm not aware of a UI framework in JS that doesn't use inheritance from outside the library.
> 1) The use of the pattern is not common in the js community.
The use of prototypes is ubiquitous in the JS community. There's no two ways about it.
Unfortunately, the avoidance of prototypes is also a common anti-pattern in the JS community, simply because JavaScript prototypes are so awkward, fragile and verbose. Doing the wrong thing with JS prototypes is easier than doing the right thing, which leads many developers to simply throw up their hands, and write code like this instead:
... which is terribly inefficient and wasteful of memory, and accomplishes nothing that a prototype couldn't do in a small fraction of the space and time.
Obviously the use of prototypes are ubiquitous in JavaScript. No one said otherwise. The use of class inheritance, as is common in other languages, like Java, C#, Python, and CoffeeScript is not common at all. Isn't that why you built it into CoffeeScript, because people were doing hacks to get super?
My point is that this is leading (and other features like await/defer will do this as well) to different design patterns. Such as Batman.js taking use of your extends keyword for consumers to implement their framework.
What you're calling "class inheritance" and what other folks call "the prototype chain" are one and the same thing. It's not built-in to CoffeeScript ... it's fundamentally built-in to JavaScript.
CoffeeScript is just making it three words:
A extends B
... instead of the usual JavaScript hoop jumping:
function ctor(){
this.constructor = A;
}
ctor.prototype = B.prototype;
A.prototype = new ctor;
Prototypal inheritance and class inheritance are not one and the same. How do I call super or base in JavaScript?
You know this, you had to add it to CoffeeScript. Do you not think the ability to call super functions leads to significantly different design patterns? If not, why did you add it? And why is EmcaScript.next probably going to have it?
Buddy, we're going around in circles here ... Yes, JavaScript lacks a way to easily call "super", but that doesn't mean that the concept doesn't exist.
Calling "super" means calling the immediate parent's version of the same function. CoffeeScript is just making it one word:
super
... instead of the usual JavaScript prototype hoop jumping:
We're going in circles because I'm talking about design patterns and you're talking about the ability to add features into JS that weren't in mind when it was designed; it can be a lisp if that's what you want. I'll gladly defer to you on what JS is ultimately capable of, it was never the point of my post. Rather my point is that the different syntax is leading to a divergence libraries and frameworks; Batman.js is a great example of a framework that, while you can consume it from JS, you probably wouldn't want to.
> Class inheritance is not a common JavaScript design pattern. It's a hack, used by a minority of JavaScript developers, in a minority of projects.
If you don’t like the way JavaScript’s prototypal inheritance works, take it up with Brendan Eich.
You are simply wrong about the commonness of using prototypes though. Nearly every big JavaScript project is organized around extending and creating prototypes, and making instances via the `new` keyword. It’s only a few zealots who militate against using that feature... and to the detriment of their followers, who end up with code that is slow and a memory hog.
TL;DR: Coffeescript should be seen as a way to enforce good Javascript style, and as such it does a decent job.
That's an interesting and very defensible PoV. However, even considered as such, it has some serious warts:
* It has no clearly-defined semantics: it's an accretion of rewriting tricks, and as such, it's often very hard to predict how two tricks will interact together, especially when they involve indentation and line-breaks.
* It tries to support too many cute idioms, which leads to too many ways to do things. There ought to be one obviously best way to do each thing, for the sake of maintenance and readability.
Now, if we consider CS as a presentation layer for JS, then its proper place is in an IDE, not as a compiler. Ideally, files should be stored as JS and converted back to CS transparently when editing. Mixes of real JS and CS->JS code should mesh together gracefully. When a piece of CS is highlighted, the corresponding JS should be shown as a tooltip. And of course, when a backtrace is produced, it should be translated from JS lines to CS lines transparently.
Today, CS fancies itself as a compiler, i.e. something which produces object code which should never be dealt with by the programmer. As such, it fails. If it presented itself as a representation/refactoring abstraction, it would be much easier to embrace. Of course, the implementation/integration with an IDE would be an order of magnitude harder than a text->text processor, and would make the language^Wtool liable to editor wars.
From the coffeescript website:
CoffeeScript is a little language that compiles into JavaScript. Underneath all those awkward braces and semicolons, JavaScript has always had a gorgeous object model at its heart. CoffeeScript is an attempt to expose the good parts of JavaScript in a simple way.
Coffeescript has never presented itself otherwise. What causes the confusion is pointless discussions about semantics and people who don't fully understand the point of coffescript teaching other people about it and writing over zealous blogposts.
All programming languages are human convenience. The computer cares not about list comprehensions or splats. It just reads hi/low. Coffeescript is a tool that enables you to write those hi/lows more conveniently. It doesn't care if its called a language or a form of mixed martial arts. It's just there to help you if you want it to.
https://en.wikipedia.org/wiki/CompilerA compiler is a computer program (or set of programs) that transforms source code written in a programming language (the source language) into another computer language (the target language ...)
> Coffeescript has never presented itself otherwise.
My point was not to disparage the author, his intentions, his lucidity, nor even the resulting language. When people receive something packaged as a compiler (a file->file traduction tool to invoke from the command line and to include in building scripts), they naturally understand it as a compiler, and judge its qualities as a compiler.
And by "compiler", I mean the informal concept that people spontaneously put behind gcc or javac, not any attempt to formally classify a kind of data conversion tool. Among associated expectations, there's this idea that the abstraction provided by the compiler doesn't leak: you generally don't need to know about ASM/bytecode while using GCC/javac. CS doesn't shield you from the generated JS, and as such, it falls short of most people's expectations about a compiler.
Looking at these expectations from a different perspective, as does Raganwald, is very interesting.
When talking about compiling computer languages. It would help if we were all using the standard definition of a compiler.
I'm glad you've got your own definition but using it only serves to confuse the discussion.
Furthermore, your argument is weak. The only reason you don't need to be more familiar with the technologies supporting gcc and javac is because they are robust and much older. If you were there at the beginning of their development you most certainly would have needed to be more familiar with their underlying platforms. In fact many would argue you'd be a better programmer if you did now.
Another reason your argument could be weak: Does a line number mapper between coffeescript and its generated javascript completely nullify your argument?
At that point I wouldn't need to ever look at the generated source and would care only about it's execution. That sounds pretty much exactly like a "compiled" language to me.
The technical term for what CoffeeScript is doing — a compiler that doesn't need a global view of the program and does local source transformations — is a transpiler.
"There ought to be one obviously best way to do each thing, for the sake of maintenance and readability."
In what way does a constriction of convention relate to readability or maintainability? The languages I'm most productive in have many ways to write readable code that accomplishes basically or exactly the same thing. I've always considered it a mark of a language's elegance and power that there would emerge multiple ways of expressing the same problem. But maybe we're thinking about different scopes here. Can you give an example?
> Now, if we consider CS as a presentation layer for JS, then its proper place is in an IDE, not as a compiler
I disagree. Forcing programmers to use a certain IDE to accomplish productivity gains is a bad road to go down. It discourages innovation, stifles competition and makes it hard to integrate the "compilation" in to other parts of your development cycle.
I taught a new programmer in my department JavaScript and CoffeeScript. Yesterday he told me he saw Notch coding a 2d version of minecraft in Java at a hackaton online, and how weird is the difference between CoffeeScript and Java.
Maybe for us there's nothing new in CoffeeScript. Heck, the patterns of programming in javascript, callbacks, functional programming, prototypes, closures, the context of this -- for him it's a lot of stuff to learn and unlearn. Sure, I came with experience in ruby and python, so learning coffee script was just one happy afternoon, but for him it is a language worth learning. keep that in mind.
For me, the web is a wild beast we are training. Rails, Coffee Script, and even more importantly - Twitter's Bootstrap are tools we use to express our products in a higher domain language. Bootstrap gives us a common UI for the web that is both beautiful and usable. The fact that I could strap in a day a snappy ajax file upload with plupload into my coffee script view means I have more time to focus on my product instead of my code. That it is less painful to change stuff. Do you ever look at your PHP code from the old days and you admire it? I admire it. I wrote crazy stuff back then. I wrote wrappers and classes and 10,000 lines of utilities just so I can put up a website half the quality of today's websites in double the time.
1. Coffee Script is a DSL for writing damn good websites.
2. (and imho) Coffee Script is a great language.
So I'm going to learn either JavaScript or CoffeeScript over January. I have some experience in VisualBasic (took a high school programming class about four years ago). Which one should I learn?
I'm a huge, huge fan of CoffeeScript, but JS will be far more useful to you right away, and your knowledge of JS will help you understand CS more when you learn it later.
Learn Javascript. Coffeescript is defined in terms of Javascript. If you don't know Javascript, learning Coffeescript will be unnecessarily difficult, because you'll have to go back and learn Javascript in bits and pieces as you learn Coffeescript. If you learn Javascript first, learning Coffeescript will be easier, because Coffeescript will build upon your Javascript knowledge.
To re-emphasize this point, there is no "choice" involved. You cannot understand Coffeescript without understanding Javascript... it almost looks like you can at first, but at soon as you start debugging you're back in "what is this prototype thing?"
On the other hand, after you work with Javascript for a little while you quickly start wishing for something like Coffeescript. It's a very natural transition, but you can't short-circuit the process.
Interesting that you point out Twitter Bootstrap -- which to me is becoming the great equalizer for new product/startup websites and a hallmark of lack of creativity or any sign of thoughtful design. Sure, the UI is great, much like the design patterns that Coffee script creates -- but what it signifies is a "dumbing down" of design much like Coffee script does to it's programmers.
In Java, good design patterns are defined and publicized, but it's up to the programmer to implement the design pattern, not the compiler. It's that sort of freedom that I feel is necessary for anything truly creative and innovative to be created.
Creativity is awesome. not in the UI. For me it means less time focusing on my product and more on remembering to make button:active look like it's pressed. for my users it means another UI to learn.
Think about trello. After two minutes on the site I was like "hellll no, I ain't gonna learn how to use this!". The UI scared me, it was too different with too little explanations.
No real classes. No type systen (optional at least would be good). No packages. No modules. No generics. No annotations, mix-ins, actors. No properties. No interfaces. No abstract classes. Horrible to maintain on large projects. Horrible tooling. Bad performance compared to VM or Native code. So much more.
I'm not sure if you're a fan of Dart or not, but it has nine of those now (classes, types, modules, generics, actors, properties, interfaces, abstract classes, and tooling) and more on the way.
Yes I like the direction dart is going in (except would prefer the type system had more actual meaning than just annotations for tooling, but still).
My pipe dream:
- Google implements a VM for dart or equivalent.
- Dart, Java, C#, ActionScript, Python, Ruby, whatever, can compile to this VM.
- VM/bytecode is initially just in chrome, which is fine as far as I am concerned (no problem saying our app works in chrome only). You can transpile to JS if you want to target other browsers.
- Because of native VM implementation in chrome, the best web applications are in chrome. Chrome increases in popularity.
- Other vendors are forced to implement this VM.
- We get to something like a client VM (lets call it CVM) standard for all browsers.
- Developer productivity improves and browser based apps start not sucking so bad in comparison to their native brothers.
Both the classes and type system are not inherently obvious: there are plenty of valid arguments for both prototype-based OO and dynamically typed languages. I personally like prototypes more than classes and am ambivalent about static/dynamic typing.
JavaScript does have packages and modules--check out CommonJS, for example. There are some issues with them in the browser, but that's a different story.
Generics and interfaces make no sense in a dynamically typed language. Abstract classes don't really make that much sense with a dynamic type system either, and they make no sense with prototype-based inheritance. Mix-ins don't make really fit into a prototype-based language either.
Properties would be nice. I don't know about tooling--js2 mode on Emacs is infinitely better than any IDE I've ever used (and I've use a bunch). I've never had issues managing JavaScript code--less issues than Java, for example--but I've never worked on anything particularly big.
JavaScript performance is now quite good. Besides, performance is not a function of the language but a function of the implementation. You wouldn't think of Scheme as a particularly fast language, but I remember recently reading about Stalin Scheme which made it as fast or faster than C.
Really, most of your arguments seem to stem from not liking prototypes and dynamic typing--these are just preferences. Complaints about JavaScript's lacking interfaces are like complaining your Tesla doesn't have a gearbox.
Your argument really makes it seem you would like nothing more than Java/C# in the browser; I personally would like little less than that. This is probably at least partly due to the name: JavaScript makes it seem like the language is akin to Java when it really only shares a superficial resemblance.
I feel bad saying this, because I respect raganwald greatly and I usually enjoy his writing, but this post is somewhere on the border between facile and false. For example:
> CoffeeScript has lots of more subtle transformations up its sleeve, like comprehensions, destructuring assignment, splats, or the "fat arrow" some rail against. Here's the secret to understand: None of these things are "language features" that compile from a language that has them—CoffeeScript—into a language that doesn't have them—JavaScript
Well, CoffeeScript does have these features, and JavaScript really doesn't have them. Would you describe JavaScript as a language that has them? Destructuring assignment doesn't exist in most implementations of JavaScript. It will have that feature later on, but it doesn't now. It also doesn't have comprehensions or splats. That's why the JavaScript that CoffeeScript generates doesn't just use JavaScript's syntax for these features — they aren't there. Instead, you have to do something else that gets the same effect.
This is also ignoring bigger changes, such as the fact that everything is an expression. That isn't true in JavaScript at all, and can't be mimicked with anything that even vaguely resembles it. You have to do what CoffeeScript does in the generated JS — constantly be storing intermediate values at the place where they're produced and assigning them afterward if you want to get a value out of most constructs (such as an if).
The two languages do correspond pretty closely, and that's intentional. But the same is true for C and machine language. If you think that C is just a shorthand for machine language, I guess you're welcome to your opinion, but you're pretty lonely with that one.
Any source language can be said to be a simple transformation of its target language, since that's what a compiler does. That doesn't mean they're the same.
Any source language can be said to be a simple transformation of its target language
Not always. There are a number of language features that have non-local implications, such as pattern matching, lazy evaluation, continuations, or exceptions. If you implement such a feature on top of a language that doesn’t have it, you will have decidedly complex transformations.
I agree that it’s overly simplistic to suggest that it isn’t a full language if it only involves local/simple transformations, but the question of local vs. non-local transformations at least hints at the idea that a new paradigm or way of thinking about programming is involved.
Nit: I think pattern matching would be local the way you are using the term; pattern matching is(/would be) implemented right at the site you use it with some form of if/else clauses that would be verbose, but obviously related to the original code. Your other three examples definitely involve large-scale "non-local" source transformation all over the place to implement them.
I say this because it took me a moment to figure out how those four things went together.
the question of local vs. non-local transformations at least hints at the idea that a new paradigm or way of thinking about programming is involved.
Which is an excellent point, and I think the essay would have been better served if you had oriented it that way, and not around the "not a language worth learning" hook.
I took part in a discussion of this idea about a month ago: http://news.ycombinator.com/item?id=3198941 There's a paper in there you would want to read as research for that essay.
This looks to me like a perfect definition of compiler:
"CoffeeScript is a program that takes some text you write using a special set of rules and transforms it into some other text, which happens to be a JavaScript program"
> None of these things are "language features" that compile from a language that has them—CoffeeScript—into a language that doesn't have them—JavaScript.
This is inane. Haskell used to compile to C. Were they not "language features"?
Clearly my writing is obtuse. Haskell has a language features—lazy evaluation for example—with no equivalent in C. Nothing about lazy evaluation compiles more-or-less 1:1 into C code, it’s a program-wide transformation.
CoffeeScript’s features are all JavaScript features, it’s a simple translation from some shorthand into some other shorthand. CoffeeScript is like the LET macro in ur-Scheme. Powerful, handy, but not a new paradigm, more like some syntactic meta-programming on top of JavaScript’s existing model of programs.
> CoffeeScript’s features are all JavaScript features,
> it’s a simple translation from some shorthand into
> some other shorthand.
This isn't entirely accurate -- in the sense that current CoffeeScript semantics can't be implemented as a series of "find-and-replace" operations into JavaScript. Some of the areas in which the AST transformations become more involved are:
* Converting arbitrary statements into expressions.
* Destructuring assignment, when mixed with splats and soaks.
So there are more advanced macros that are being used. It's not doing much a lisp couldn't do. I mean, look at scribble. It's still racket, even though it has not an s-exp in sight.
Chains of soaked invocations are just a Maybe Monad anyways. It's nothing too out there. You could write them in normal javascript fine.
Haskell wasn't simply sugaring the regular C design patterns. The C that the compiler generated was nothing like the C that you would normally write.
A better example would be Objective C compiling to C. And I would agree that early Objective C wasn't really a language that added new paradigms to C. It sugared good coding practices for the most part, and did little else. As a result, I generally recommended a combination of the K&R book and the ObjC language spec to learn it -- buying books for ObjC was a waste of time, since it was such a thin wrapper around C.
Coffeescript doesn't even have its own standard library, much less a runtime being cross-compiled with its own garbage collector and stack frame constructs.
Even accepting the basic premise of the article, that CS doesn't strictly give you anything you can't get with JS, I still don't see any of the reason explain why I shouldn't write CS instead.
Even if there are no language features CS gives me over JS (and there are -- list comprehensions to name one), I get cleanliness. The Sapir-Whorf hypothesis is just as relevant in programming languages as in human languages. Equivalent JS being "possible" is not a reason to not write easier to understand and more maintainable code with a language that lets me expend less effort to arrive at the same place.
MVC Web Framework for NodeJS written in CoffeeScript.
This is an open source project that has just been released, and from my experience developing it, here are my conclusions:
I believe some people are comfortable coding one way, and others are comfortable coding another. Anyways, everybody uses what works. At the end, the productivity you've got and the time you save is all that matters.
Regarding the issue with the stack traces and CoffeeScript, you're right, line numbers are not accurate, but if you know where the problem is and you'll know how to debug it, on the spot.
I was not attracted to CoffeeScript myself when I first saw it, but after having a closer look, I finally realized it is a great tool to use when applicable. Then I decided to migrate the whole code to CS.
From my experience, it's all about your coding workflow. Knowing CoffeeScript syntax and how it translates to JavaScript. I use CoffeeScript's simplicity to implement complicated concepts that would require some ellaboration when it comes to syntax.
There is a increasing trend: many people do not want to code in JavaScript. This is happening because more and more engineers with experience in other languages are forced to deal with JS now days and they are trying to come up with alternate approaches.
I for one hope something succeeds, but would prefer more of a bytecode in browser solution than transpiling to JS. One can dream.
He says that Coffeescript formalizes design patterns for Javascript. If you agree with those that say design patterns highlight language deficiencies (http://c2.com/cgi/wiki?AreDesignPatternsMissingLanguageFeatu...), then the existence of Coffeescript is a significant indicator.
I find these <strike>anti</strike>-CoffeeScript articles annoying. I use CoffeeScript, because it works for me. If it doesn't work for you, whatever, write plain JavaScript.
This article just argues over what is and what is not a language.
Syntax matters in every way. If you think @foo is prettier than this.foo, and you get to write the former every day instead of the latter, you will write better code, be more productive, and love life a little bit more. Programmers hate to admit that they like nice things, but my experience confirms it.
I've always found the Perlis quote to be false. It seems to assume that existing languages align well with how I think.
A good quip only needs a grain of truth I suppose, but for that reason I wouldn't give such a quip a prominent place in a logical argument.
Raganwald: as much as I enjoy your writing, this condenses to a sentence. The Apple Summarizer actually did a good job:
"And if you value making JavaScript easier to read by virtue of getting everyone to solve the same problems the same way with the same Design Patterns, CoffeeScript is a good tool for getting everyone else to write good JavaScript."
Does this really deserve a full article and a bait-and-switchy headline?
I consistently write long essays and I lack the patience to edit them to manageable length. More importantly, I lack the moral fibre to discard perfectly good points. Any fool can chop filler out of an essay. It takes an author of sterling character to discard perfectly good ideas in the interest of making what remains an even better essay.
And I lack that character. Having written words about an idea I like, I find it very difficult to let go of them, and my writing suffers for it.
Ah, I was not saying TL;DR. I don't mind long. I don't even mind Steve Yegge long.
What bugged me about this article was the deliberate misdirection, which seemed to me not to have any function in the article. For me it felt like it was just to arrive at a simple point in a more complex way (and thus pad the length out).
But there's a huge scope for misunderstanding in these things, so I apologize for assuming too mcuh here. Maybe you thought it would be amusing to come at it from a different angle. Maybe I read it too quickly to appreciate that.
131 comments
[ 45.6 ms ] story [ 503 ms ] threadOh, and when you are writing you are almost always writing for an audience -- esp. when you tweet the result right afterwards and show up on Hacker News to discuss it.
Nothing you have said is wrong.
I'm trying coffee on a relatively small project with only a few developers. So far I'm happy with the tradeoff. I keep my Coffeescript simple so the Javascript is almost exactly what I would write by hand.
That is what we do for example in Hallo Editor: https://github.com/bergie/hallo
"CoffeeScript isn't a language worth learning because it isn't a language. It doesn't make you think about programming in a new way"
How is that a definition of a language? It compiles down to another language sure - but what doesn't?
For example, the (in)famous equivalence between 10[p] and p[10] point to C being a kind of translator rather than an entirely new way to think about programs.
I consider it a different language if for no other reason than, if a programmer familiar only with Javascript looked at code written in Coffeescript, they would not understand it at all. And it can't be converted to Javascript without either considerable hand work, or via an automated tool.
But as long as the underlying model is the same, and as long as it’s a leaky abstraction, I don’t think of it as a separate language.
For example, if it were to be a separate language I would look for its OOP stuff to be implemented in the “engine” and not to be strongly related to the JavaScript prototype mechanism.
In general, langages don't tend to have multiple grammars (although spoke languages tend to be looser than written), and perhaps the unnaturalness of having a second grammar might undermine your position.
There's a 1-1 mapping of CoffeeScript syntax to JavaScript syntax. This is really useful when you are debugging. But it cannot introduce much useful new behavior.
That's why I'd agree its more appropriate to see CoffeeScript as a new syntax for JavaScript, than as a new programming language.
I posted that article a little prematurely and more as a rant for my co-workers. It was a bit misunderstood (and it blew up online before I even knew it so I didn't bother editing).
My point in that quote was that bad CoffeeScript is worse than bad JavaScript.
Good CoffeeScript is better than good JavaScript.
Bold statement, explanation?
I'm just not sure if it's enough to make up for a less-than-optimal debugging experience, especially considering that most of us don't write really excellent code all the time.
That doesn't mean that it's not OK to prefer it over JavaScript (or vice versa) if you find those differences make you happier about coding in it.
Not true, if only because CoffeeScript includes classes as a language feature. In JavaScript it is a hack. This might change with EmcaScript.next, but for now that creates a significantly different way to design your code.
Try writing a Batman.js app in JavaScript and you'll see what I mean. With await/defer possibly being merged into CS, we're going to see the languages diverge further in the future.
Specifically, most major JavaScript projects have some kind of class implementation which makes inheritance, creating new classes, &c. easier. Some of these are quite elegant, but they end up being annoying anyway, because each system is slightly different. CoffeeScript takes one particular pattern (which is thankfully compatible with the expectations of Google's Closure compiler) and gives it a shorthand, so that everyone writing CS code will be on the same page.
The crux of the argument is that when you write CoffeeScript you think in JavaScript. But I absolutely never think about overriding a parent function in JavaScript. In CoffeeScript this is actively encouraged.
Like I said, as other ideas like await/defer become more mature (and are merged into mainline), we're going to see the design patterns diverge futher.
1) The use of the pattern is not common in the js community. 2) If someone does use the pattern, they might be using a different implementation.
That you can override an Object's toString is not what we're talking about here jashkenas. We're talking about creating an Animal class and extending it with Horse.
Uh, if you're using the Closure libraries, you very likely are extending goog.Control or goog.Component. I don't know dojo, but from my brief perusal of the docs it looks like you do the same thing with dojo.declare. YUI seems to do the same with Widget. I'm not aware of a UI framework in JS that doesn't use inheritance from outside the library.
Unfortunately, the avoidance of prototypes is also a common anti-pattern in the JS community, simply because JavaScript prototypes are so awkward, fragile and verbose. Doing the wrong thing with JS prototypes is easier than doing the right thing, which leads many developers to simply throw up their hands, and write code like this instead:
... which is terribly inefficient and wasteful of memory, and accomplishes nothing that a prototype couldn't do in a small fraction of the space and time.My point is that this is leading (and other features like await/defer will do this as well) to different design patterns. Such as Batman.js taking use of your extends keyword for consumers to implement their framework.
CoffeeScript is just making it three words:
... instead of the usual JavaScript hoop jumping:You know this, you had to add it to CoffeeScript. Do you not think the ability to call super functions leads to significantly different design patterns? If not, why did you add it? And why is EmcaScript.next probably going to have it?
Calling "super" means calling the immediate parent's version of the same function. CoffeeScript is just making it one word:
... instead of the usual JavaScript prototype hoop jumping:Thanks for the fun back and forth.
Here are some popular big JavaScript toolkits/frameworks: Closure Library, YUI, Dojo, Prototype, MooTools, ExtJS, Base2, JavaScriptMVC, Backbone.
http://closure-library.googlecode.com/svn/docs/closure_goog_...
http://yuilibrary.com/yui/docs/api/classes/Base.html
http://livedocs.dojotoolkit.org/dojo/declare
http://api.prototypejs.org/language/Class/
http://mootools.net/docs/core/Class/Class
http://docs.sencha.com/ext-js/4-0/#!/api/Ext.Base
http://base2.googlecode.com/svn/version/1.0.2/doc/base2.html...
http://javascriptmvc.com/docs.html#!jQuery.Class
http://documentcloud.github.com/backbone/docs/backbone.html#...
* * *
And here are some other helpful resources:
http://www.aminutewithbrendan.com/pages/20110216
http://www.quora.com/How-was-classical-inheritance-*supposed...
http://www.2ality.com/2011/06/prototypes-as-classes.html
http://ejohn.org/blog/simple-javascript-inheritance/
http://my.safaribooksonline.com/book/programming/javascript/...
http://javascript.crockford.com/prototypal.html
http://bolinfest.com/javascript/inheritance.php
http://dmitrysoshnikov.com/ecmascript/chapter-7-2-oop-ecmasc...
If you don’t like the way JavaScript’s prototypal inheritance works, take it up with Brendan Eich.
You are simply wrong about the commonness of using prototypes though. Nearly every big JavaScript project is organized around extending and creating prototypes, and making instances via the `new` keyword. It’s only a few zealots who militate against using that feature... and to the detriment of their followers, who end up with code that is slow and a memory hog.
That's an interesting and very defensible PoV. However, even considered as such, it has some serious warts:
* It has no clearly-defined semantics: it's an accretion of rewriting tricks, and as such, it's often very hard to predict how two tricks will interact together, especially when they involve indentation and line-breaks.
* It tries to support too many cute idioms, which leads to too many ways to do things. There ought to be one obviously best way to do each thing, for the sake of maintenance and readability.
Now, if we consider CS as a presentation layer for JS, then its proper place is in an IDE, not as a compiler. Ideally, files should be stored as JS and converted back to CS transparently when editing. Mixes of real JS and CS->JS code should mesh together gracefully. When a piece of CS is highlighted, the corresponding JS should be shown as a tooltip. And of course, when a backtrace is produced, it should be translated from JS lines to CS lines transparently.
Today, CS fancies itself as a compiler, i.e. something which produces object code which should never be dealt with by the programmer. As such, it fails. If it presented itself as a representation/refactoring abstraction, it would be much easier to embrace. Of course, the implementation/integration with an IDE would be an order of magnitude harder than a text->text processor, and would make the language^Wtool liable to editor wars.
Coffeescript has never presented itself otherwise. What causes the confusion is pointless discussions about semantics and people who don't fully understand the point of coffescript teaching other people about it and writing over zealous blogposts.
All programming languages are human convenience. The computer cares not about list comprehensions or splats. It just reads hi/low. Coffeescript is a tool that enables you to write those hi/lows more conveniently. It doesn't care if its called a language or a form of mixed martial arts. It's just there to help you if you want it to.
https://en.wikipedia.org/wiki/Compiler A compiler is a computer program (or set of programs) that transforms source code written in a programming language (the source language) into another computer language (the target language ...)
My point was not to disparage the author, his intentions, his lucidity, nor even the resulting language. When people receive something packaged as a compiler (a file->file traduction tool to invoke from the command line and to include in building scripts), they naturally understand it as a compiler, and judge its qualities as a compiler.
And by "compiler", I mean the informal concept that people spontaneously put behind gcc or javac, not any attempt to formally classify a kind of data conversion tool. Among associated expectations, there's this idea that the abstraction provided by the compiler doesn't leak: you generally don't need to know about ASM/bytecode while using GCC/javac. CS doesn't shield you from the generated JS, and as such, it falls short of most people's expectations about a compiler.
Looking at these expectations from a different perspective, as does Raganwald, is very interesting.
I'm glad you've got your own definition but using it only serves to confuse the discussion.
Furthermore, your argument is weak. The only reason you don't need to be more familiar with the technologies supporting gcc and javac is because they are robust and much older. If you were there at the beginning of their development you most certainly would have needed to be more familiar with their underlying platforms. In fact many would argue you'd be a better programmer if you did now.
Another reason your argument could be weak: Does a line number mapper between coffeescript and its generated javascript completely nullify your argument?
At that point I wouldn't need to ever look at the generated source and would care only about it's execution. That sounds pretty much exactly like a "compiled" language to me.
I think you'll find this point of contention won't work against raganwald: https://github.com/raganwald/rewrite_rails
https://github.com/fab13n/parsec-coffee-script
In what way does a constriction of convention relate to readability or maintainability? The languages I'm most productive in have many ways to write readable code that accomplishes basically or exactly the same thing. I've always considered it a mark of a language's elegance and power that there would emerge multiple ways of expressing the same problem. But maybe we're thinking about different scopes here. Can you give an example?
I disagree. Forcing programmers to use a certain IDE to accomplish productivity gains is a bad road to go down. It discourages innovation, stifles competition and makes it hard to integrate the "compilation" in to other parts of your development cycle.
Maybe for us there's nothing new in CoffeeScript. Heck, the patterns of programming in javascript, callbacks, functional programming, prototypes, closures, the context of this -- for him it's a lot of stuff to learn and unlearn. Sure, I came with experience in ruby and python, so learning coffee script was just one happy afternoon, but for him it is a language worth learning. keep that in mind.
For me, the web is a wild beast we are training. Rails, Coffee Script, and even more importantly - Twitter's Bootstrap are tools we use to express our products in a higher domain language. Bootstrap gives us a common UI for the web that is both beautiful and usable. The fact that I could strap in a day a snappy ajax file upload with plupload into my coffee script view means I have more time to focus on my product instead of my code. That it is less painful to change stuff. Do you ever look at your PHP code from the old days and you admire it? I admire it. I wrote crazy stuff back then. I wrote wrappers and classes and 10,000 lines of utilities just so I can put up a website half the quality of today's websites in double the time.
1. Coffee Script is a DSL for writing damn good websites. 2. (and imho) Coffee Script is a great language.
I'm a huge, huge fan of CoffeeScript, but JS will be far more useful to you right away, and your knowledge of JS will help you understand CS more when you learn it later.
On the other hand, after you work with Javascript for a little while you quickly start wishing for something like Coffeescript. It's a very natural transition, but you can't short-circuit the process.
It really covers the how and why of JS in a way that will make your understanding sharper.
In Java, good design patterns are defined and publicized, but it's up to the programmer to implement the design pattern, not the compiler. It's that sort of freedom that I feel is necessary for anything truly creative and innovative to be created.
Think about trello. After two minutes on the site I was like "hellll no, I ain't gonna learn how to use this!". The UI scared me, it was too different with too little explanations.
CoffeeScript is [not a language] worth learning.
Might be worth giving it a try.
My pipe dream: - Google implements a VM for dart or equivalent.
- Dart, Java, C#, ActionScript, Python, Ruby, whatever, can compile to this VM.
- VM/bytecode is initially just in chrome, which is fine as far as I am concerned (no problem saying our app works in chrome only). You can transpile to JS if you want to target other browsers.
- Because of native VM implementation in chrome, the best web applications are in chrome. Chrome increases in popularity.
- Other vendors are forced to implement this VM.
- We get to something like a client VM (lets call it CVM) standard for all browsers.
- Developer productivity improves and browser based apps start not sucking so bad in comparison to their native brothers.
JavaScript does have packages and modules--check out CommonJS, for example. There are some issues with them in the browser, but that's a different story.
Generics and interfaces make no sense in a dynamically typed language. Abstract classes don't really make that much sense with a dynamic type system either, and they make no sense with prototype-based inheritance. Mix-ins don't make really fit into a prototype-based language either.
Properties would be nice. I don't know about tooling--js2 mode on Emacs is infinitely better than any IDE I've ever used (and I've use a bunch). I've never had issues managing JavaScript code--less issues than Java, for example--but I've never worked on anything particularly big.
JavaScript performance is now quite good. Besides, performance is not a function of the language but a function of the implementation. You wouldn't think of Scheme as a particularly fast language, but I remember recently reading about Stalin Scheme which made it as fast or faster than C.
Really, most of your arguments seem to stem from not liking prototypes and dynamic typing--these are just preferences. Complaints about JavaScript's lacking interfaces are like complaining your Tesla doesn't have a gearbox.
Your argument really makes it seem you would like nothing more than Java/C# in the browser; I personally would like little less than that. This is probably at least partly due to the name: JavaScript makes it seem like the language is akin to Java when it really only shares a superficial resemblance.
> CoffeeScript has lots of more subtle transformations up its sleeve, like comprehensions, destructuring assignment, splats, or the "fat arrow" some rail against. Here's the secret to understand: None of these things are "language features" that compile from a language that has them—CoffeeScript—into a language that doesn't have them—JavaScript
Well, CoffeeScript does have these features, and JavaScript really doesn't have them. Would you describe JavaScript as a language that has them? Destructuring assignment doesn't exist in most implementations of JavaScript. It will have that feature later on, but it doesn't now. It also doesn't have comprehensions or splats. That's why the JavaScript that CoffeeScript generates doesn't just use JavaScript's syntax for these features — they aren't there. Instead, you have to do something else that gets the same effect.
This is also ignoring bigger changes, such as the fact that everything is an expression. That isn't true in JavaScript at all, and can't be mimicked with anything that even vaguely resembles it. You have to do what CoffeeScript does in the generated JS — constantly be storing intermediate values at the place where they're produced and assigning them afterward if you want to get a value out of most constructs (such as an if).
The two languages do correspond pretty closely, and that's intentional. But the same is true for C and machine language. If you think that C is just a shorthand for machine language, I guess you're welcome to your opinion, but you're pretty lonely with that one.
Any source language can be said to be a simple transformation of its target language, since that's what a compiler does. That doesn't mean they're the same.
Not always. There are a number of language features that have non-local implications, such as pattern matching, lazy evaluation, continuations, or exceptions. If you implement such a feature on top of a language that doesn’t have it, you will have decidedly complex transformations.
I agree that it’s overly simplistic to suggest that it isn’t a full language if it only involves local/simple transformations, but the question of local vs. non-local transformations at least hints at the idea that a new paradigm or way of thinking about programming is involved.
I say this because it took me a moment to figure out how those four things went together.
Which is an excellent point, and I think the essay would have been better served if you had oriented it that way, and not around the "not a language worth learning" hook.
I will say that just like you should know HTML before using haml, you should know JavaScript before using CoffeeScript.
Objective-C -> MacRuby; Slim/HAML/Jade -> HTML; SASS/LESS -> CSS and so on...
"CoffeeScript is a program that takes some text you write using a special set of rules and transforms it into some other text, which happens to be a JavaScript program"
This is inane. Haskell used to compile to C. Were they not "language features"?
CoffeeScript’s features are all JavaScript features, it’s a simple translation from some shorthand into some other shorthand. CoffeeScript is like the LET macro in ur-Scheme. Powerful, handy, but not a new paradigm, more like some syntactic meta-programming on top of JavaScript’s existing model of programs.
* Converting arbitrary statements into expressions.
* Destructuring assignment, when mixed with splats and soaks.
* Chains of soaked invocations, like:
* Class bodies as blocks of executable code.Chains of soaked invocations are just a Maybe Monad anyways. It's nothing too out there. You could write them in normal javascript fine.
A better example would be Objective C compiling to C. And I would agree that early Objective C wasn't really a language that added new paradigms to C. It sugared good coding practices for the most part, and did little else. As a result, I generally recommended a combination of the K&R book and the ObjC language spec to learn it -- buying books for ObjC was a waste of time, since it was such a thin wrapper around C.
Coffeescript is in a similar position.
Even if there are no language features CS gives me over JS (and there are -- list comprehensions to name one), I get cleanliness. The Sapir-Whorf hypothesis is just as relevant in programming languages as in human languages. Equivalent JS being "possible" is not a reason to not write easier to understand and more maintainable code with a language that lets me expend less effort to arrive at the same place.
MVC Web Framework for NodeJS written in CoffeeScript.
This is an open source project that has just been released, and from my experience developing it, here are my conclusions:
I believe some people are comfortable coding one way, and others are comfortable coding another. Anyways, everybody uses what works. At the end, the productivity you've got and the time you save is all that matters.
Regarding the issue with the stack traces and CoffeeScript, you're right, line numbers are not accurate, but if you know where the problem is and you'll know how to debug it, on the spot.
I was not attracted to CoffeeScript myself when I first saw it, but after having a closer look, I finally realized it is a great tool to use when applicable. Then I decided to migrate the whole code to CS.
From my experience, it's all about your coding workflow. Knowing CoffeeScript syntax and how it translates to JavaScript. I use CoffeeScript's simplicity to implement complicated concepts that would require some ellaboration when it comes to syntax.
I for one hope something succeeds, but would prefer more of a bytecode in browser solution than transpiling to JS. One can dream.
This article just argues over what is and what is not a language.
But the title says "CoffeeScript is not worth learning".
No, it says "it's not a language worth learning". The author's point is that CoffeeScript is not a language, but a tool for JavaScript.
"And if you value making JavaScript easier to read by virtue of getting everyone to solve the same problems the same way with the same Design Patterns, CoffeeScript is a good tool for getting everyone else to write good JavaScript."
Does this really deserve a full article and a bait-and-switchy headline?
http://raganwald.posterous.com/why-i-downvote-tldr-comments-...
What bugged me about this article was the deliberate misdirection, which seemed to me not to have any function in the article. For me it felt like it was just to arrive at a simple point in a more complex way (and thus pad the length out).
But there's a huge scope for misunderstanding in these things, so I apologize for assuming too mcuh here. Maybe you thought it would be amusing to come at it from a different angle. Maybe I read it too quickly to appreciate that.