View Full Version : Code I wrote whilst angry

08-09-2008, 08:22 PM
I just used this code to vent some frustration earlier, hope you all like it. It's pretty self-explanatory. It's probably too theoretical to go into the DD scripts archives, so I'll just leave it lying about here.

var Generic = (function() {
var MATCH_FAIL = {},
MATCH_ANY = function() { return MATCH_ANY; };

function create(fallback) {
var s = function() {
for (var i = 0, args = Array.prototype.slice.call(arguments), r; i < specs.length; ++i)
if ((r = specs[i].match(args)) !== MATCH_FAIL)
return r;

if (s._fallback)
return s._fallback.apply(this, args);

throw new Error("Generic: No methods matched and no fallback provided.");
}, specs = s._specs = [];

s.specialise = specialise;
s.addFallback = addFallback;
if (fallback)

return s;

function specialise(patterns, func) {
var s = this._specs;

s[s.length] = new Specialisation(patterns, func, this);

return this;

function addFallback(func) {
this._fallback = func;

return this;

/**** Begin Specialisation ****/

function Specialisation(patterns, func, context) {
this.patterns = patterns;
this.func = func;
this.context = context;

Specialisation.compatible = function(value, pattern) {
if (pattern === MATCH_ANY && value !== undefined)
return true;
else if ((typeof pattern === "string" || pattern instanceof String) && typeof value === pattern)
return true;
else if (typeof pattern === "function" && value instanceof pattern)
return true;
else if (pattern instanceof Pattern)
return pattern.guard(value);
else if (pattern instanceof Interface)
return pattern.match(value);

return false;

Specialisation.prototype = {
match: function(args) {
for (var i = 0, a = this.patterns, n = a.length; i < n; ++i)
if (!Specialisation.compatible(args[i], a[i]))
return MATCH_FAIL;

return this.func.apply(this.context, args);

/**** Begin Pattern ****/

function Pattern(guard) {
this.guard = guard;

function GUARD(func) {
return new Pattern(func);

function GUARD_IS(right) {
return new Pattern(function(val) {
return val === right;

/**** Begin Interface ****/

function Interface(obj) {
if (!(this instanceof Interface))
return new Interface(obj);

for (var x in obj)
if (obj.hasOwnProperty(x))
this[x] = obj[x];

Interface.getSkeleton = function(obj) {
var r = {};

for (var x in obj)
if (obj.hasOwnProperty(x))
r[x] = typeof obj[x];

return new Interface(r);

Interface.prototype = {
match: function(value) {
for (var x in this)
if (this.hasOwnProperty(x) && !Specialisation.compatible(value[x], this[x]))
return false;

return true;

return {
create: create,
Interface: Interface,

function Animal(species) {
this.species = species;

var iAnimal = Generic.Interface.getSkeleton(new Animal("foo"));

var iDog = Generic.Interface({'species' : Generic.GUARD_IS("dog")});

var sound = Generic.create()
.specialise([iDog, 'undefined'], function() {
print("I got a dog! I got one!");
.specialise(['string', iAnimal], function(snd, an) {
print("A " + an.species + " says '" + snd + "',");
.specialise([iAnimal, 'string'], function(an, snd) {
print("but a " + an.species + " says '" + snd + "',");
.specialise([Animal], function(an) {
print("and a " + an.species + " is apparently silent.");
.specialise([Generic.MATCH_ANY, 'undefined'], function(val) {
print("... and whatever noise a " + val + " makes...");
.addFallback(function() {
print("Er... random animal noise?");

sound(new Animal("dog"));
sound("woof", new Animal("dog"));
sound(new Animal("cat"), "miaow");
sound(new Animal("frog"));
sound(4, 5);

08-09-2008, 08:23 PM
and a cow says: MOO...

08-09-2008, 08:24 PM
Only if you specialise to it. :)

08-09-2008, 08:26 PM
Uh I tested it, and all that happened was it printed a blank page.

08-09-2008, 08:27 PM
sound("MOO", new Animal("cow"));

08-09-2008, 08:27 PM
The print() statements I used are meant for running in a console, change them to alert() or something if you intend to run it in a browser.

What it does isn't remarkable, that's just standardly-idiotic sample code. What's hopefully interesting is how it does it.

08-09-2008, 08:35 PM
Yeah I'm not entirely sure what it does. It just looks like the Generic method creates functions?

08-09-2008, 08:38 PM
No, it's a crude implementation of dispatching to functions based on argument types — one way of doing classical OO in a purely-functional language. It can be thought of in terms of Haskell's typeclasses, or Common Lisp's... well, generics; that latter was the inspiration for this.

Simply, a single generic is created, and then onto that generic can be attached various specialisations to various argument types. When the generic is called, unlike a traditional function, it inspects its arguments and dispatches the call and the arguments to the appropriate specialisation. My implementation here caters to Javascript's split personality with regards to OO by allowing dispatching using both duck-typing via interfaces, and by type or instance as reported by typeof and instanceof.

08-09-2008, 08:51 PM
Ah I see... I think I understand it. A little bit, at least.

08-09-2008, 10:25 PM
typeof pattern === "function" || pattern instanceof Function

I tested on IE and FF and you don't need the latter half for functions.

"Structure and Interpretation of Computer Programs" (http://deptinfo.unice.fr/~roy/sicp.pdf) (large PDF link) talks about this type of dispatch if anyone is curious. (Begins talking about it on 2.4)

08-09-2008, 10:32 PM
You're right, typeof new Function() === "function". *trim*

I didn't know you still lurked around here, Trinithis :)

08-09-2008, 10:34 PM
I sometimes do :D

08-10-2008, 12:13 AM
Normal people punch things when they get angry!

What on earth does it actually do?

08-10-2008, 02:02 AM
Interesting code. What ticked you off?

08-10-2008, 12:04 PM
Dal: I explained it in an earlier post (the interesting bit, anyway: it also prints out various animal noises, but... no-one cares about that). Trinithis also linked to a book (an excellent book, by the way, which I highly recommend) which covers this amongst other topics.
Interesting code. What ticked you off?Eh, various things.

08-10-2008, 01:59 PM
Interesting code. What ticked you off?
Eh, various things.

Was there a woman involved? I guess I deserved that short answer in trade for mine. Well you certainly haven't given us any reason here not to tick you off. ;)

I especially liked (and I may be seeing the code wrong, so I guess I should say, "what looks to me like") the use of an anonymous function as an object in the global scope. But I will be scratching my head for awhile over exactly why. I thought that there wasn't much point in having an anonymous function other than getting all but its execution out of the global scope.

08-10-2008, 03:31 PM
You are indeed seeing that incorrectly, I believe. The function is called. However, there are some situations in which the pattern you describe is useful; I use it in my 'DOM' toolkit, something like this:
var Dom = (function() {
var r = function(s) {
// CSS selector stuff

r.byName = function(s) {
return document.getElementsByName(s);

return r;
})();Which allows code like:
var someEl = Dom("#some-id"),
someOtherEls = Dom.byName("and-a-name"),
andSomeMoreEls = Dom(".some-class");... where the most useful function is more easily accessible (at the cost of being named less descriptively).

08-10-2008, 03:39 PM
Fantastic stuff, Im sure I may even use this one day but I have no need for it at the moment. Im a noob at javascript, only 4 months experience. Thanks to C/C++ Im doing fine but functions like even the one above is a little too OOP for getting things done.


08-10-2008, 03:52 PM
Well, you'll never have a need for it. It's a convenience. Rather than:
function foo(arg) {
if (typeof arg === "string") {
} else if (typeof arg === "number") {
} else {
}You would:
var foo = Generic.create(quux);
foo.specialise(['string'], bar);
foo.specialise(['number'], baz);It's particularly interesting because it's a convenience that can be used to implement a form of object orientation that's much more powerful than Java's or C++'s.

08-10-2008, 04:03 PM
I suppose theres only one question remaining in that case;

What can you come up with when your happy? ;)

Thanks for the reply Twey :)

08-10-2008, 05:29 PM
Frustratingly little. :(

08-10-2008, 05:30 PM
Frustratingly little. :(

lol :)

08-11-2008, 03:56 AM
I'm the same as Twey here... I even start typing faster and everything when I'm angry :p

12-27-2009, 06:26 AM
Whoa, totally forgot about this generics (Twey's) code. I happened to write something similar a few months ago for the interested: