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.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 (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) 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 :))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.As a result, I'm increasingly inclined to do data-structure objects and composable functions, which seems similar to Go's approach.
1 http://perfectionkills.com/instanceof-considered-harmful-or-...
Objects are a poor man's closures.
Source: http://c2.com/cgi/wiki?ClosuresAndObjectsAreEquivalent. Be sure to click through to the original source thread. It's a fascinating discussion.
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.