

My Perception of CoffeeScript - activestylus
http://leongersing.tumblr.com/post/11561298378/my-perception-of-coffeescript

======
jashkenas
This essay is fairly amazing -- there's so much emotion and so many assertions
packed into it, and yet they're all founded on innuendo and hearsay, not on
how things actually are. Most of the things Leon writes are factually
incorrect, but at the same time, you can see how listening to enough FUD might
make you start to think them...

For example:

    
    
        > CoffeeScript classes have attributes and properties that 
        > are encouraged to be mutated by reference so a language 
        > contrivance was devised (@) to allow OO style encapsulation 
        > while still trying to provide Functional referential 
        > transparency in anonymous contexts… wrap your head around that.
    

What? Instances of CoffeeScript classes are just like any other JavaScript
object with a prototype -- just like any old string or function or array. The
"language contrivance" `@` symbol is simply an alias for `this`. Nothing more
and nothing less. `@name` in CoffeeScript is just `this.name` in JavaScript --
I'm not sure how you wind up with "functional referential transparency in
anonymous contexts" from there ... but I'll have a little of whatever Leon's
smoking ;)

There's many other things in the essay, but the core boils down to this: There
are a bunch of folks who are used to ignoring prototypes in JavaScript because
they hand-roll objects by manually adding properties or using Crockford's
"module pattern". For them, CoffeeScript's `class` keyword feels like it's
adding something alien to JavaScript because it makes prototypes accessible.
It's not. Using prototypes and objects lies at the core of JavaScript, and
it's only the difficult and fragile syntax that leads people to manufacture
new instances like this:

    
    
        var makeDog = function() {
          return {
            bark: function(){},
            run: function(){},
            ...
          };
        };
    

Instead of the _far_ more efficient:

    
    
        new Dog;
    

Finally, CoffeeScript isn't encouraging you to do anything in particular. If
you truly don't like using prototypes in JS, feel free not to use `class` in
CS.

    
    
        > Jeremy Ashkenas, whom I do not know but would 
        > LOVE to have a drink with (alcoholic drink or 
        > otherwise) and pick his brain ...
    

Ping me the next time you're in NYC. Always happy to grab a drink and talk
shop.

~~~
activestylus
Nice to have you chime in here Jeremy. I personally use CoffeeScript a lot. I
also code in Ruby and understand its appeal from that perspective. However I
am curious what your take is on dxbydt's reply below. He makes a very
interesting comment about the overhead of objects vs simple message
passing/currying/etc.

~~~
jashkenas
My take is that it's a classic straw man -- you can write inefficient
functional code that constantly manufactures and throws away closures ... just
as easily as you can write inefficient object-oriented code that constantly
manufactures and throws away objects.

The point of object-orientation is that "simple message passing/currying/etc"
rarely stays simple for long. Eventually your system wants to have many
different pieces of data that all share common functionality, and objects are
a great way to model that. But if you prefer to work procedurally, and have a
big data structure and a bunch of little functions that operate on it --
that's fine too. CoffeeScript and JavaScript support both.

~~~
oinksoft
I note the same in another part of this thread, showing how you can write his
JS in less CS code.

However, I'd argue that the reason most people are adopting CoffeeScript is
for the "class ... extends" as it lets them model their JavaScript code much
like they might have in their old Java, and more likely, PHP projects. And
once you throw that out, the main draws remaining are default argument values,
string interpolation, and the ? operator.

The question is, do those benefits warrant the added layer of complexity? Many
of us who have worked with JavaScript for a very long time wonder about this,
and dread the deeply nested class hierarchies we might encounter in CS
projects because CS makes that so _easy_ to do. But bad programmers will write
bad code in any language, and I hate to think what a dev who uses `class ...
extends` as a crutch would write in plain JavaScript. So, I have both positive
and indifferent feelings about CoffeeScript, the only negatives being with the
handling of variable scope/shadowing, which is of course opinionated and
neither right nor wrong, and the parser itself which makes for ugliness like

    
    
      window.addEventListener 'load', ->
        # Do stuff ...
      , false
      # leading comma is needed above.

~~~
roopeshv
the only reason i use CS is because I can get away with typing way less than
needed. There is a one time cost (huge? or not!) for setting up tooling to
compile it automatically.

If not anything, typing is the only reason I love CS. Because studies have
shown (anyone got links, i know them from greg wilson's talk from CUSEC)

1) Less lines of code - less mistakes

2) You produce same number of lines of code, no matter the language

and (not related to studies) 3) less lines to debug 4) if you can deal with
the idiosyncrasies of JS, that person can deal with CS quite well. (stawman
argument anyone?)

------
lazerwalker
> If you’re a fan of OO you’re going to love CoffeeScript from day one,
> guaranteed. If you’ve never tried to see the world through Functional
> glasses then I assert that you’re going to be missing out on a few beautiful
> vistas.

I feel like he's not using the same CoffeeScript I am. Yes, it does make OO-
style programming easier than vanilla JS, but it also makes functional
programming a heck of a lot more accessible. The terser function creation
syntax and the 'everything is an expression' mindset might appear at first
glance to be minor improvements, but they add up to a language where working
in a functional paradigm is a _lot_ more enjoyable than regular JS.

~~~
LeonidasXIV
I have to agree with you here. Since using CS my code got far more functional
because I could create functions that create functions really easy and the
implicit returns make it feel like a functional language.

------
gmac
The author has 3 main gripes: backticks to drop back to JS, the 'class'
keyword, and the fat ('this'-preserving) arrow.

But these are all features you can blithely ignore: don't use backticks, and
stick to native JS prototypes and the thin arrow.

At which point you're left with, from where I'm sitting, a less noisy, more
concise, more enjoyable way to program the web browser than plain JS.

~~~
dxbydt
Frankly his main gripe is that JS = FP, CoffeeScript = OO.

The 3 gripes you point out are mostly a consequence of Coffee choosing to do
OO instead of FP & then needing hooks into JS's world to achieve this end.
From the article - "CoffeeScript sees the world through OO’s eyes. When I see
JavaScript, I find beauty in it’s ability to be a dynamically typed Functional
programming language."

His example is known by various other names, most commonly
<http://www.google.com/search?q=lots+of+little+objects>

He wants just 2 "objects" ( he more specifically wants unstructured objects,
or plain structs ) - sammy the python & tommy the horse. Functional JS gives
him just those 2. But OO CoffeeScript gives you 5, or even 6 if you count
hasProp.( var Animal, Horse, Snake, sam, tom, __hasProp. )

The more dramatic way to document this behavior is to have say 100 cats & 500
rats, whoe identity is captured in an int. With FP you'll be able to happily
get away with just 2 "objects" - 1 cat and 1 rat ! The int indexing will
happen via a function call. With OO you will have 600 little objects plus a
bunch more for the classes and the hasProp !!

Here's another one I've seen - If you get two programmers to write a
paddleball - one in functional JS, and the other using Coffee OO. The Coffee
one will lag pretty soon. The Coffee guy will have a Ball object & a Brick
object & a Wall object & each gesture will get captured as an object as well.
So when the player moves the arrow keys to move the paddle, each move's x,y
coordinates will become a gesture object & then gestures are passed to the
ball & the wall to determine collisions....soon you'll have 1000s of gestures
& the pgm will slow down unpredictably as the gc kicks in. The functional JS
guy won't create a single gesture object, he'll simply call some collision
detection function directly with the x & y, so you'll see much better
performance.

Ofcourse the coffee OO code will look a lot prettier than the FP one littered
with curlies & function calls, but like the author says, "JavaScript’s
function keyword and curly brackets aren’t ugly to me, they are useful
indicators of code smells."

So pick your poison.

~~~
oinksoft
I am not a fan of CoffeeScript for my own reasons (it doesn't offer enough for
me to drop drop JS), but there is nothing stopping the author from writing his
CS like so:

    
    
      move = (aDistanceOf) ->
        it = @name or "It"
        alert arguments[1] if arguments[1]
        "#{it} moved #{aDistanceOf} meters"
      
      snake =
         name: "Sammy"
      horse =
         name: "Tommy"
      
      move.call snake, 5, "Slitering"
      move.call horse, 45, "Galloping"
    

But really, this is just JS wearing some new clothes. The string interpolation
is nice, but apart from that, you really gain nothing over the JS version.

~~~
schiffern
>But really, this is just JS wearing some new clothes.

And that's not a bad thing.

If you want FP _and_ encapsulation, you can write something like this
(functionally equivalent to the OO version, unlike TFA's example)

    
    
      move = ->
        alert "#{@move_verb or "Mov"}ing..."
        alert "#{@name or "It"} moved #{@distance or 1} meters"
    
      snake =
         name: "Sammy"
         distance: 5
         move_verb: "Slither"
    
      horse =
         name: "Tommy"
         distance: 45
         move_verb: "Gallop"
      
      move.call snake
      move.call horse

~~~
dxbydt
Dude. Really ? You've just invented objects, but you'd rather not call it
that. You have two attributes ( name & distance ) and you've made an attribute
out of the method ( move_verb ?! heh heh ) as well, very clever. You are then
calling a function & asking it to sort it all out. If we are going to call
this FP, that's a real stretch. What objects buy you is that name,distance &
move_verb are common to both snake & horse, so they should be refactored to
some base class & then snake & horse should be instances of that class. But
then you won't do OO, so you must encapsulate in this roundabout fashion:)
I'll grant it does give you FP + encapsulation.

~~~
jhickner
shiffern's example uses the same coding style you use in Clojure. It doesn't
feel like stretch to call it FP. Start with a basic data structure (the object
in shiffern's example would translate to a map in Clojure) and then operate on
it with simple functions.

    
    
      (def snake {:name "Sammy" 
                  :distance 5 
                  :move-verb "Slither"})
    
      (def horse {:name "Tommy" 
                  :distance 45 
                  :move-verb "Gallop"})
    
      (defn move[{:keys [name distance move-verb]}]
        (println (str (or move-verb "Mov") "ing..."))
        (println (or name "It") "moved" (or distance 1) "meters")) 
    
      (move snake)
      (move horse)

~~~
dxbydt
or in scala:

    
    
        val snake = Map("name"->"Sammy", "dist"->"5m","move"->" slithers ")
        val horse = Map("name"->"Tommy", "dist"->"45m","move"->" gallops ")
        def move(m: Map[String,String]) = println( m("name") + m("move" ) + m("dist")
    
         scala> move (snake)
         Sammy slithers 5m
         scala> move (horse)
         Tommy gallops 45m
    

If FP = OO via dictionaries, then yeah, ok :))

~~~
nivertech
The example given by author is very FP and not OOP, since the move function
doesn't modify shared state and the only side-effect is output.

We use CoffeeScript for node.js and browser client code. I think classes more
useful for control patterns, like EventEmitter in node.js, and much less for
wrapping of data, as done in traditional Java/C++ -style OOP or ORM models.

I'll chip in Erlang (real production-grade code with type-specs, not a short
REPL example):

    
    
        -module(animal).
    
        -record(animal{ 
                        name      :: string(),
                        distance  :: integer(),
                        move_verb :: string()
                      }).
    
        -spec move(animal()) -> ok.
        move(#animal{name=Name, distance=Distance, move_verb=MoveVerb}) -> 
          io:format("~sing... ~s moved ~b meters~n", 
                    [default(MoveVerb, "Mov"), default(Name, "It"), default(Distance,1)]).
    
        -spec default(X::any(), Val::any()) -> any().
        default(undefined,Val) -> Val.
        default(X,        _)   -> X.
    
        -spec main() -> ok.
        main() ->
          Snake = #animal{name      = "Sammy",
                          distance  = 5, 
                          move_verb = "Slither"},
    
          Horse = #animal{name      = "Tommy", 
                          distance  = 45, 
                          move_verb = "Gallop"},
    
          [move(A) || A <- [Snake, Horse]],
          ok.

------
tinutinu
'I agree with this' is not same as 'objective and balanced'.

~~~
activestylus
True that - I actually disagree with his final conclusion, because you can
still program functionally in CS. I embraced JS prototypes a long time ago and
have no need for the OO magic offered by CS. That said I still prefer it for a
good chunk of my development.

Coffee vs JS rants typically degenerate into emotional outbursts, I was
impressed by the author's overall restraint and advocacy for both approaches

------
lucian1900
CoffeeScript's classes _are_ the extend functionality in underscore/backbone.
Perhaps they're misnamed a little, but they're extremely simple. Just read the
generated code.

~~~
cmwelsh
This is my favorite reply, because it's exactly right. No one is stopping you
from mixing and matching paradigms either! You can extend CoffeeScript classes
with extra mixins.

I think CoffeeScript's class keyword does a great job at what it's trying to
do: make all the complexities of prototypical inheritance accessible to the
average person who just wants simple object-oriented classes. CoffeeScript is
just JavaScript.

------
danso
This may sound pedantic, but I wish that these type of technical screeds were
created with the flexibility/power of online publishing in mind.

There needs to be more thought given to the use of non-prose in communicating
these things. More tables, a la Ed Tufte's principle of direct comparison and
small multiples, is a huge help. At the very least, it helps break up dense
text and forces the author to be more aware of how to best not bury important
statements and assertions.

But if you aren't going to go all-in and use tables/graphics because it's a
bit of work...then at least use headings, bulleted lists, formatted-
text...this is the web, after all.

Or, if you don't even want to do that, at least use line breaks like everyone
learns about.

And if you plan on including code, please use a wide enough format (and of
course, syntax highlighting, though that is additional overhead).

I don't mean to belittle this author's point on the basis of visual cues
alone. It's just that I see a lot of great essays that could be so much more
influential and effective with just some additional effort put into
presentation.

------
stcredzero
_It’s not the that Object modeling metaphor used in CoffeeScript is bad, it’s
just overly object-oriented and builds on OO style inheritance._

There are lots of people who don't even include inheritance in their
definitions of OO.

------
smoyer
And the next technical book to be published? ... "Coffeescript - The Good
Parts"

On a more serious note, I love Coffeescript and am adept at Javascript. But
since we have both of them, I get to choose.

~~~
wwweston
Then we can move on to inventing EspressoScript: It's the Good Parts of
CoffeeScript, and not the bad!

~~~
smoyer
Which will of course be forked to LatteScript, CappacinoScript and
MachiatoScript. Real non-conformists will insist on TeaScript (or its fork -
ChaiScript). After years of infighting, the industry will finally get behind a
standard based on the least common denominator - CaffeineScript which will
prompty be sued out of existence by the Caffeine JVM (overlay on .NET?).

By then, young developers will be so disillusioned with the whole process that
they'll invent something totally different ... and who can blame them ;) Due
to the vocal nature of its supporters, RubyRedGrapefruitScript becomes the
default scripting language available in modern browsers.

I'm glad I know assembly language ... I can always go back to the beginning ;)

~~~
jashkenas
As often happens, the truth is more interesting than the satire...

Coco: <https://github.com/satyr/coco>

LiveScript: <http://gkz.github.com/LiveScript/>

IcedCoffeeScript: <http://maxtaco.github.com/coffee-script/>

Parsec CoffeeScript: <https://github.com/fab13n/parsec-coffee-script>

UberScript: [https://github.com/jstrachan/coffee-
script/blob/master/TypeA...](https://github.com/jstrachan/coffee-
script/blob/master/TypeAnnotations.md)

ToffeeScript: <https://github.com/jiangmiao/toffee-script>

Kaffeine: <http://weepy.github.com/kaffeine/>

~~~
smoyer
Haha ... I only knew about a couple of them but that's quite a list. And we
haven't even started listing the coffee-named projects related to Java (like
Kaffe - <http://www.kaffe.org/>). I think I'd better quit now and get some
code written!

------
blrblr
It makes more sense for CoffeeScript to exists as an independent language,
rather than as a JavaScript generator.

The syntax is beautiful, it had potential; why be a difficult-to-debug
JavaScript 'compiler' instead?

~~~
rimantas
I'd say this "difficult-to-debug" attitude comes from those who did not
actually tried to work with CoffeeScript and just think that would be the
case. We have a lot of code in it already and debugging was never an issue.

~~~
base698
+1 here too.

