Skip to content

Instantly share code, notes, and snippets.

@mcav
Created November 30, 2014 03:13
Show Gist options
  • Save mcav/175869643bcc48cefa41 to your computer and use it in GitHub Desktop.
Save mcav/175869643bcc48cefa41 to your computer and use it in GitHub Desktop.
Dead-simple Clojure-style multimethods for JavaScript. Public Domain.
/**
* Dead-simple multimethods for JavaScript.
*
* Usage:
*
* var count = multimethod([
* String, function(self) {
* return self.length;
* },
* Number, function(self) {
* return self;
* },
* Error, function(self) {
* return self.stack.length;
* }
* ]);
*/
(function(global) {
var multimethodId = 0;
function multimethod(name, implArrayMap) {
if (implArrayMap === undefined) {
implArrayMap = name;
name = 'multimethod' + (++multimethodId);
}
console.log(name);
var map = new Map();
for (var i = 0; i < implArrayMap.length;) {
var constructor_ = implArrayMap[i];
if (typeof constructor_ === "string") {
constructor_ = global[constructor_];
}
map.set(implArrayMap[i++], implArrayMap[i++]);
}
name = "$multi_" + name;
var typeMap = new WeakMap();
return function(self) {
var impl = self[name];
if (!impl) {
impl = map.get(self.constructor) || map.get("default");
if (!impl) {
throw new Error("No method defined for type: " + self.constructor);
}
self.constructor.prototype[name] = impl;
}
return impl.apply(null, arguments);
}
}
global.multimethod = multimethod;
})(typeof window !== "undefined" || this);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment