polymorphic
Version:
Create functions with different argument signatures for different code flows
77 lines (59 loc) • 2.06 kB
JavaScript
;
var polymorphic = require('../lib/polymorphic'), // you'd use require('polymorphic')
util = require('util'),
blame = require('blame');
// we want to have a function which works well with dates
// an easy way to achieve this is to have a polymorphic function with a signature allowing only Date objects
var dater = polymorphic();
// add the signature for Date objects
dater.signature('Date', function(date) {
// we know date is an instance of Date
console.log(date, String(date));
});
dater(new Date()); // all is well
try {
// now lets call it with a number
dater(12345);
}
catch (e) {
// throws Error: polymorph: signature not found "int|number"
// we use our `blame` module to show a more narrowed down error stack
var item = blame.stack(e).filter(module.filename).item();
console.log(String(item));
}
// Lets dive in a little deeper, inheritance
// these examples are taken from our unit test (test/complex.js), which features a lot more examples
function Foo() {
this.name = 'Foo';
this.time = Date.now();
}
Foo.prototype.hello = function() {
return 'a ' + this.name;
};
function Bar() {
Bar.super_.apply(this, arguments);
this.name = 'Bar';
this.date = new Date();
}
util.inherits(Bar, Foo);
// ok, so now a Bar inherits from Foo, meaning it will have everything Foo has, with some added or different stuff
var complex = polymorphic();
// we will be allowing anything which is (inherited) from Foo
complex.signature('Foo', function(foo) {
// call the 'hello' method on the foo, which we know is there as it is always defined on a Foo
return foo.hello();
});
console.log(
complex(new Foo()), // a Foo
complex(new Bar()) // a Bar
);
// so, what if we don't really trust the inherited instances?
// we can ensure we have a specific instance by narrowing it down to only the defined type
complex.signature('Foo!', function(foo) {
// here, foo is always a Foo, never a Bar
return foo.hello() + '!!';
});
console.log(
complex(new Foo()), // a Foo!!
complex(new Bar()) // a Bar
);