CLOS-like object system


A CLOS-like object system in JavaScript.

  • Multiple inheritance
  • Multiple dispatch
  • Type checking on construction
  • ML (or Haskell) style datatype
  • Guarded functions (simple patternmatching)
  • Memoization (optional)
  • Partial application

Examples use cases are shown in:

var fib = define_generic(true); //pass true to enable memoization 
define_method(fib, [0], function () { return 0; });
define_method(fib, [1], function () { return 1; });
define_method(fib, ["number"], function (n) {
  return fib(n-1) + fib(n-2);
= require('./examples/prelude');
var add = define_generic();
define_method(add, ["number", "number"], function (ab) { return a + b; });
define_method(add, ["string", "string"], function (ab) { return a + b; });
p.map(add(2), [1,2,3,4,5]); //=> [3,4,5,6,7] 
p.map(p.flip(add)("!!!"), ["lisp", "alien", "rocks"]); //=> ["lisp!!!", "alien!!!", "rocks!!!"] 
//class, when `make`d, retruns a hash of values 
var book = define_class([], function (x) {
    return slot_exists(x, 'title', "string")
        && slot_exists(x, 'author', "string");
//generic function show 
var show = define_generic();
//show an instance of book 
define_method(show, [book], function (b) {
    return b.title + " by " + b.author;
var p_city = make(book, {title:'Permutation City', author:'Greg Egan'});
//define a bunch of classes 
//the name is optional 
var floor  = define_class([], , "floor");
var carpet = define_class([], , "carpet");
var ball   = define_class([], , "ball");
var glass  = define_class([], , "glass");
var stick  = define_class([], , "stick");
//function to display the result 
var bumpOutput = function(xyresult){
    console.log(+ ' + ' + y + ' bump = ' + result);
//define a generic function `bump` 
var bump = define_generic();
//define methods 
define_method(bump, [ball, floor], function(xy){
    bumpOutput(x, y, 'bounce');
define_method(bump, [glass, floor], function(xy){
    bumpOutput(x, y, 'crash');
define_method(bump, [stick, floor], function(xy){
    bumpOutput(x, y, 'knock');
//if you prefer, the following works, too 
bump.defMethod([, carpet], function(xy){
    bumpOutput(x, y, 'silence');
//call the methods 
bump(new ball, new floor); //should bounce 
bump(new glass, new floor); //should crash 
bump(new stick, new carpet); //shold silince 
bump(new floor, new stick); //  method 


  • an arrey of classes to inherit from. (required)
  • a validator function called upon instance construction. (optional)
  • a name string which is used as the string representation of its instances (optional)

Returns a constructor function (called class) that can be newed or get applied to make

define_class([ parent classes ], function (x) { protocol }, name);

var x = define_class([]);
var y = define_class([x]);
var z = define_class([x, y], funciton (a) {
  return slot_exists(a, 'name', 'string');

Takes nothing.

Returns a generic function.


var show = define_generic();


  • a generic function (required)
  • an array of patterns that specifies the type of arguments given to the method (required)
  • a function that is the body of the method (required)

A pattern is either

  • a class (compared with instanceof)
  • a value (compared with ===)
  • a constructor (that is defined with define_constructor)
  • a string returned by typeof operator ("number", "function", etc)
  • undefined for wildcard

Returns void.

define_method( generic function , [ patternA , ... ], function ( a , ... ) { body });

define_method(show, [z], function (a) {
define_method(show, [x], function (a) {
  console.log("an instance of x");

define_constructor allows a class to have multiple constructors.


  • a class (required)
  • an initialization function (optional)

Returns a constructor function.

define_constructor( class , function (...) { return make(class, {...}); });

var rank = define_class();
var Ace = define_constructor(rank);
var Jack = define_constructor(rank);
var Queen = define_constructor(rank);
var King = define_constructor(rank);
var Num = define_constructor(rank, function (n) { return make(rank, {number: n});  });
isA(Jack(), rank); //true 


  • a class (required)
  • a hash object specifying the initial values of each slot (optional)

Returns an instance of the class.

make( class, { slot_name: initial_value, ...});

make(z, {name: "foo"});
make(z); //ERROR 

The hash object given as the second argument is matched with the function given as the second argument to define_class. If the result is false, an exception gets thrown.


  • an instance (required)
  • a class or a string (required)

Returns boolean


  • an instance (required)
  • a slot identifier (required)
  • a class or a string to specify the type (optional)

Returns a boolean. True if the instance has the slot of the specified type. False otherwise.