CoffeeScript is a simple, clean, fast language which compiles to JavaScript, either at build time, with a caching framework plugin on the server, or at runtime in the browser.

The syntax looks like a cross between Python and Haskell1 and, generally speaking, is used similarly enough to Python that you’ll have little trouble picking it up and using it comfortably.

It does have a few of what non-Ruby programmers will consider distasteful warts, but for the most part, it’s an elegant and delightful language.

You’ll probably want to keep the syntax reference open in a background tab at first, but if you’re comfortable with Python and you’ve done any programming with jQuery or some other modern JavaScript library, you’ll feel right at home.

Below, I’ve summarized the points which the documentation doesn’t completely prepare you for as a Python programmer.

Helpful features with no direct Python analogue

A.K.A. Things which you’ll probably forget to use at first, but which you really should work to remember.

Use almost anything as an expression Not only does CoffeeScript have anonymous functions, you can treat pretty much anything as an expression and it’ll be wrapped in an anonymous function if needed. Indent-stripping multi-line strings If you use single-quotes rather than triple-quotes for multi-line strings, it’ll still work and leading indentation common to all lines will be stripped. (like textwrap.dedent() , if you’re familiar with it) Embedding expressions in strings Given how much string templating is done in JavaScript, it really helps that you can put any expression directly inside the Ruby-style #{string interpolation operator} for own key of To iterate over only the properties which weren’t inherited, use for own key of rather than for key of . (Very useful since JavaScript doesn’t make a distinction between properties and associative array keys) Fat-arrow function syntax To bind this to the parent object, even in a callback, simply define it with => rather than -> Ultra-concise constructors Rather than filling your class constructors with this.foo = foo , you can simply use the @ shorthand for this. and write constructor: (@foo, @bar) -> with an empty method body. Checking for the existence of variables and properties is concise. Use variable ? "default value" and obj.method?().thing?.widget

Similarities and differences with Python not explicitly mentioned

A.K.A. What the documentation won’t directly prepare you for if you have Python instincts.

Ternary syntax will break your muscle memory For a ternary expression, Python uses result = a if test else b while CoffeeScript uses result = if test then a else b . (The if statement syntax on a single line) a = b and c or d works Pythonically but you don’t need backwards-compatibility with pre-ternary Python releases Boolean operators don’t coerce the return value to a boolean (a will be c or d, not true or false) but 99% of the time, what you really want is the ternary operator. Comprehensions use when , not if If you write result = (x for x in list if x % 2 == 0) , you won’t get an error… but you will get a loop inside a conditional rather than a conditional inside a loop.

(If item in the parent scope isn’t evenly divisible by 2, the loop will be skipped. If it is, result will be identical to list ) Comprehensions iterating two lists produce a two-dimensional array In Python, this syntax will produce a one-dimensional list while, in CoffeeScript, it produces a list of lists. a+b for a in A for b in B newList = list1 + list2 + list3 is not array concatenation You could use newList = [].concat list1, list2, list3 instead, but a cleaner and more flexible alternative is to use splats. This example cleanly concatenates three lists and two individual numbers into a single list: newList = [listA..., numA, numB, listB..., listC...] In my opinion, this makes CoffeeScript cleaner and more intuitive than Python for this task.

When foo is an array, if foo is always true [] != false so, to check whether a list is empty, you have to do if foo.length instead. someFunction(arg3 = 1) is not the syntax for positional arguments …but because assignment is valid in an expression, it won’t raise an error. What you want is someFunction null, null, 1 or someFunction(null, null, 1) There is an equivalent to someFunction(x, y, *args) As in Python, splats aren’t just for function definitions. someFunction x, y, args...

A.K.A. Where most of your subtle, hard-to-find bugs will come from as a Python programmer.

If you don’t use parentheses in a function call, CoffeeScript will guess them for you …but Haskell programmers and shell scripters will be surprised when a b c d means a(b(c(d))) rather than a(b,c,d) . This also means that foo () is sometimes invalid when foo() is OK. On the plus side, it works very well for ensuring that anonymously defined callbacks aren’t an exception to the “indents, not braces” block syntax. The rules are simple but it’ll still take some getting used to before I’ll stop occasionally tripping over them. Here’s how jashkenas explained it to me: The call wraps forwards to the end of the line, or to the end of the indented block, with one specific exception for postfix conditionals. alert a alert(a) alert inspect a alert(inspect(a)) alert inspect a if b alert(inspect(a)) if b Colons aren’t part of the block syntax Habitually typing a colon after a function name or control statement will turn it into an object property (think dict literals)… which can do all manner of crazy things if it’s something like “else:” which is still valid CoffeeScript. You can’t shadow a higher-level variable …only refer to it as in Ruby’s “local scope”, so expect to cause subtle bugs if you habitually reuse a handful of temporary variable names. If you want to get out of the habit, PyLint‘s default configuration will complain when you do this in your Python code. Like Perl and Ruby and unlike JavaScript, CoffeeScript does implicit returns …so expect subtle bugs until you internalize that CoffeeScript’s function syntax is really a multi-line lambda.

(As the docs say when talking about comprehensions intended only for their side-effects, “Be careful that you’re not accidentally returning the results of the comprehension in these cases, by adding a meaningful return value, like true, or null, to the bottom of your function.”) As with PHP, single- and double-quoted strings have different meanings …with interpolation only working in double-quoted strings. Like in C and many C-inspired syntaxes, and explicitly unlike Python, you can do assignment inside an expression. So expect to shoot yourself in the foot on occasion by accidentally typing = instead of == and not getting an error message. (You can, however, reduce the risks by habituating yourself to the is and isnt aliases for == and != )

Caveats to re-mention for JavaScript programmers

A.K.A. Where subtle, hard-to-find bugs may come from if you have a lot of experience working with plain old JavaScript.

Switch statements don’t allow you to fall-through to the next case CoffeeScript automatically inserts break; into every case. However, when statements will accept comma-separated lists instead. (I seem to have misplaced the response which gave me this tip. Help appreciated in tracking it down so I can link it.) To avoid namespace pollution, everything is run in an anonymous wrapper …so you have to explicitly attach things to the window object if that’s what you want. == and != are converted into === and !== If you really want the intransitive, coercion-inducing version, wrap the expression in backticks to mark it as raw, untranslated JavaScript. CoffeeScript’s in is Python’s in JavaScript’s in is CoffeeScript’s of .

Python features still to find equivalents for

Concise any(iterable) , all(iterable) , and reduce(function, sequence) without relying on Underscore.coffee or ECMAScript 5.

Did I miss something?

I’m new to CoffeeScript, so please let me know if I’m wrong or if I forgot to mention some area where Python instincts will steer you wrong with CoffeeScript.

Also, don’t forget to read the FAQ. It’s not as noticeable as the docs, but it’s almost as useful. 🙂

1. Technically, the syntax is inspired by Ruby and YAML, but I know quite a few Python programmers for whom that wouldn’t mean anything, so I compare to Python and Haskell first instead.

A Python programmer’s first impression of CoffeeScript by Stephan Sokolow is licensed under a Creative Commons Attribution-ShareAlike 4.0 International License.