Hacker Monthly #23 by Netizens Media

Hacker Monthly #23 by Netizens Media

Author:Netizens Media [Media, Netizens]
Language: eng
Format: epub, mobi, pdf
Publisher: Netizens Media
Published: 2012-04-02T16:42:41+00:00


By DAVID NOLEN

I’ve been spending a lot of time recently hacking on the ClojureScript language [github.com/clojure/clojurescript]. I can say without qualification that I haven’t had this much fun programming since I first taught myself JavaScript nearly seven years ago. So let’s put aside logic programming for a moment and let’s talk about code complexity and code expressivity.

Recently on StackOverflow someone asked how to idiomatically construct a type in ClojureScript. Before we get into that, let’s consider how this is done in JavaScript:

// 193 characters

var Foo = function(a, b, c){

this.a = a;

this.b = b;

this.c = c;

}

Foo.prototype.bar = function(x){

return this.a + this.b + this.c + x;

}

var afoo = new Foo(1,2,3);

afoo.bar(3);

CoffeeScript gets a lot of deserved attention for its brevity for common tasks. For example the same thing in CoffeeScript:

# 106 characters

class Foo

constructor: (@a, @b, @c) ->

bar: (x) -> @a + @b + @c + x

afoo = new Foo 1, 2, 3

afoo.bar 3

That requires nearly half the amount of characters. Of course on real code the code compression isn't nearly that great — perhaps 10-20% in my experience. Still, I find that CoffeeScript tends to give the feeling of compression for many common tasks, and how a language feels day in and day out is important for programmer happiness.

Let's take a look at the same thing in ClojureScript:

;; 130 characters

(defprotocol IFoo

(bar [this x])) ;; 93 characters w/o this!

(deftype Foo [a b c]

IFoo

(bar [_ x] (+ a b c x)))

(def afoo (Foo. 1 2 3))

(bar afoo 3)

The ClojureScript without the strange protocol form would give even better compression than CoffeeScript! So what does this protocol form do, and why do we need that cluttering up our type definition?

ClojureScript, unlike JavaScript or CoffeeScript, promotes defining reusable abstractions. Imagine if all the types in your favorite library were swappable with your own implementations? Hmm...perhaps that's an abstraction too far for many users of JavaScript or CoffeeScript.

Well, here's a use case I think more people will get: neither JavaScript nor CoffeeScript provides any kind of doesNotUnderstand: hook that is fantastic for providing default implementations.

(defprotocol IFoo

(bar [this x]))

(extend-type default

IFoo

(bar [_ x] :default))

(bar 1) ; >> :default

We've extended all objects including numbers to respond to the bar function. We can provide more specific implementations at anytime, i.e. by using extend-type on string, array, Vector, even your custom types instead of default. It's important to note that this extension is safe and local to whatever namespace you defined your protocol.

Still not convinced? Let's demonstrate a very powerful form of extension that even Dart is getting behind.

In ClojureScript it's simple to construct types which act like functions. While this might sound esoteric, consider very succinct operations like the following:

(def address {:street "1010 Foo Ave."

:apt "11111111"

:city "Bit City"

:zip "00000000"})

(map address [:street :zip])

;; >> ("1010 Foo Ave." "00000000")

Wow. HashMaps in ClojureScript are functions! Now this may look like some special case provided by the language, but that's not true. ClojureScript eats its own dog food; the language is defined on top of reusable abstractions.

How can we leverage this? An example: JavaScript and CoffeeScript both let you extract a range from strings and arrays.



Download



Copyright Disclaimer:
This site does not store any files on its server. We only index and link to content provided by other sites. Please contact the content providers to delete copyright contents if any and email us, we'll remove relevant links or contents immediately.