---
layout: deckjs
title: Type classes in JavaScript
description: Presentation at pdxfunc 2012-03
author: Jesse Hallett
---
create = (db, document) ->
deferred = new $.Deferred()
$.getJSON("/_uuids").success (resp) ->
id = resp.uuids[0]
docURL = "/#{db}/#{id}"
$.putJSON(docURL, document).success ->
$.getJSON(docURL).success (updatedDoc) ->
deferred.resolve updatedDoc
deferred
create = (db, document) ->
deferred = new $.Deferred()
$.getJSON("/_uuids").success (resp) ->
id = resp.uuids[0]
docURL = "/#{db}/#{id}"
$.putJSON(docURL, document).success ->
$.getJSON(docURL).success (updatedDoc) ->
deferred.resolve updatedDoc
deferred
|
function create(db, document) {
var deferred = new $.Deferred()
$.getJSON("/_uuids").success(function(resp) {
var id = resp.uuids[0];
var docURL = "/"+ db +"/"+ id;
$.putJSON(docURL, document).success(function() {
$.getJSON(docURL).success(function(updatedDoc) {
deferred.resolve(updatedDoc);
});
});
});
return deferred;
}
|
asyncFunction = (arg) ->
deferred = new $.Deferred()
doStuff arg, (result) ->
deferred.resolve result
deferred
asyncFunction("foo").done (result) ->
print result
|
asyncFunction = (arg, callback) ->
doStuff arg, (result) ->
callback(result)
asyncFunction "foo", (result) ->
print result
|
create = (db, document) ->
deferred = new $.Deferred()
$.getJSON("/_uuids").success((resp) ->
id = resp.uuids[0]
docURL = "/#{db}/#{id}"
$.putJSON(docURL, document).success( ->
$.getJSON(docURL).success((updatedDoc) ->
deferred.resolve updatedDoc
).error (xhr, textStatus) ->
deferred.reject xhr, textStatus
).error (xhr, textStatus) ->
deferred.reject xhr, textStatus
).error (xhr, textStatus) ->
deferred.reject xhr, textStatus
deferred
create = (db, document) ->
do
resp <- $.getJSON "/_uuids"
id = resp.uuids[0]
docURL = "/#{db}/#{id}"
_ <- $.putJSON docURL, document
updatedDoc <- $getJSON docURL
yield
updatedDoc
create = (db, document) ->
$.getJSON("/_uuids").flatMap (resp) ->
id = resp.uuids[0]
docURL = "/#{db}/#{id}"
$.putJSON(docURL, document).flatMap (_) ->
$.getJSON(docURL).map (updatedDoc) ->
updatedDoc
$.Deferred.prototype.flatten = ->
deferred = new $.Deferred()
this.done (deferredPrime) ->
deferredPrime.done (values...) ->
deferred.resolve values...
deferredPrime.fail (msgs...) ->
deferred.reject msgs...
this.fail (msgs...) ->
deferred.reject msgs...
deferred
$.Deferred.prototype.map = (f) ->
deferred = new $.Deferred()
this.done (values...) ->
deferred.resolve (f values...)
this.fail (msgs...) ->
deferred.reject msgs...
deferred
$.Deferred.prototype.flatMap = (f) ->
(this.map f).flatten
create = (db, document) ->
$.getJSON("/_uuids").flatMap (resp) ->
id = resp.uuids[0]
docURL = "/#{db}/#{id}"
$.putJSON(docURL, document).flatMap ->
$.getJSON(docURL).map (updatedDoc) ->
updatedDoc
|
create = (db, document) ->
deferred = new $.Deferred()
$.getJSON("/_uuids").success((resp) ->
id = resp.uuids[0]
docURL = "/#{db}/#{id}"
$.putJSON(docURL, document).success( ->
$.getJSON(docURL).success((updatedDoc) ->
deferred.resolve updatedDoc
).error (xhr, textStatus) ->
deferred.reject xhr, textStatus
).error (xhr, textStatus) ->
deferred.reject xhr, textStatus
).error (xhr, textStatus) ->
deferred.reject xhr, textStatus
deferred
|
gameOfLife = (board) ->
do
row <- board
cell <- row
yield
{ x, y, isAlive } = cell
stillAlive = switch neighborCount(x, y)
when 2 then isAlive
when 3 then true
else false
{ x: x, y: y, isAlive: stillAlive }
flatMap = (obj, f) ->
if $.isArray obj
mapped = obj.map f
mapped.reduce ((out, e) -> out.concat e), []
else
obj.flatMap f
class Show a where
show :: a -> String
instance Show String where
show s = s
show "foo" == "foo"
instance (Show a) => Show [a] where
show l = "["++ (intercalate "," $ map show l) ++"]"
show [1, 2, 3, 4] == "[1, 2, 3, 4]"
(defprotocol Show
"Produce a string representation of a given value"
(show [a] "returns a string representation of a"))
(deftype Foo [])
(deftype Bar [prop])
(extend Foo Show
{:show (fn [x] "foo")})
(extend Bar Show
{:show (fn [x] (let [s show (. x prop)]
(str "bar[" s "]")))})
(let [foo (new Foo)]
(= (show foo) "foo"))
(let [foo (new Foo)
bar (new Bar foo)]
(= (show bar) "bar[foo]"))
Show = Protocol
show: Protocol.required
extend String, Show
show: (s) -> s
extend Array, Show
show: (a) -> "["+ (a.map (e) -> show e).join(", ") +"]"
show "foo" == "foo"
show ["foo", "bar"] == "[foo, bar]"
Functor = new Protocol
map: Protocol.required
Monad = new Protocol
flatMap: (m, f) -> Monad.flatten (Functor.map m, f)
flatten: (m) -> Monad.flatMap m, (v) -> v
compose: (m, k) -> Monad.flatMap m, (_) -> k
create = (db, document) ->
do
resp <- $.getJSON "/_uuids"
id = resp.uuids[0]
docURL = "/#{db}/#{id}"
_ <- $.putJSON docURL, document
updatedDoc <- $getJSON docURL
yield
updatedDoc
Protocol = (signatures) ->
@impls = {}
findImpl = (object) ->
constructor = object.constructor
impl = @impls[constructor]
if impl
impl
else if (constructor and
constructor.prototype and
constructor.prototype !== Object
getImplementation constructor.prototype
Object.keys(signatures).forEach (name) =>
@[name] = (firstArg, args...) ->
impl = findImpl firstArg
func = impl[name]
func firstArg, args...
Protocol = (signatures) ->
@impls = {}
findImpl = (object) ->
@impls["__protocol_crumb__"]
Object.keys(signatures).forEach (name) =>
@[name] = (firstArg, args...) ->
impl = findImpl firstArg
func = impl[name]
func firstArg, args...
Protocol.counter = 0
extend = (type, protocol, impl) ->
type.prototype["__protocol_crumb__"] = Protocol.counter
protocol.impls[Protocol.counter] = impl
Protocol.counter += 1
_ = undefined
signature = Protocol.signature
Functor = new Protocol (a) ->
map: signature _, a
extend Array, Functor,
map: (f, array) -> array.map f