polygamous.js
function method(dispatch) {
  var branches      = []
  var baseline      = function(a){ throw noBranchFor(a) }
  var dispatchTable = new DispatchTable()

  dispatch = dispatch || identity

  return makeMethod(function() {
    var value  = dispatch.apply(null, arguments)
    var branch = dispatchTable.getBranch(value).code
              || branchMatching(value, branches).code
              || baseline

    return branch.apply(null, arguments)
  })


  // #### Function makeMethod
  //
  // Adds modification methods to a multi-method.
  //
  // :: method -> method
  function makeMethod(f) {
    f.when     = when
    f.fallback = fallback
    f.remove   = remove
    f.clone    = clone

    return f
  }

  // ### Function when
  //
  // Adds a branch to a multi-method.
  //
  // :: @method => A, (B... -> C) -> method
  function when(condition, f) {
    if (branchMatching(condition, branches).code)  throw ambiguousBranch(condition)

    branches.push({ condition: condition, code: f })
    dispatchTable.add(condition, f)
    return this
  }

  // ### Function fallback
  //
  // Adds a baseline branch, which is evaluated if no other branches
  // match a given dispatch value.
  //
  // :: @method => (A... -> B) -> method
  function fallback(f) {
    baseline = f
    return this
  }

  // ### Function remove
  //
  // Removes a branch from the multi-method.
  //
  // :: @method => A -> method
  function remove(condition) {
    branches = branches.filter(function(a) {
                                 return !equal(condition, a.condition)
                               })
    return this
  }

  // ### Function clone
  //
  // Creates a new multi-method that fallsback to this one.
  //
  // :: @method => Unit -> method
  function clone() {
    var instance = method(dispatch)
    instance.fallback(this)
    return instance
  }
}
function method(dispatch) {
  var branches      = []
  var baseline      = function(a){ throw noBranchFor(a) }
  var dispatchTable = new DispatchTable()

  dispatch = dispatch || identity

  return makeMethod(function() {
    var value  = dispatch.apply(null, arguments)
    var branch = dispatchTable.getBranch(value).code
              || branchMatching(value, branches).code
              || baseline

    return branch.apply(null, arguments)
  })


  // #### Function makeMethod
  //
  // Adds modification methods to a multi-method.
  //
  // :: method -> method
  function makeMethod(f) {
    f.when     = when
    f.fallback = fallback
    f.remove   = remove
    f.clone    = clone

    return f
  }

  // ### Function when
  //
  // Adds a branch to a multi-method.
  //
  // :: @method => A, (B... -> C) -> method
  function when(condition, f) {
    if (branchMatching(condition, branches).code)  throw ambiguousBranch(condition)

    branches.push({ condition: condition, code: f })
    dispatchTable.add(condition, f)
    return this
  }

  // ### Function fallback
  //
  // Adds a baseline branch, which is evaluated if no other branches
  // match a given dispatch value.
  //
  // :: @method => (A... -> B) -> method
  function fallback(f) {
    baseline = f
    return this
  }

  // ### Function remove
  //
  // Removes a branch from the multi-method.
  //
  // :: @method => A -> method
  function remove(condition) {
    branches = branches.filter(function(a) {
                                 return !equal(condition, a.condition)
                               })
    return this
  }

  // ### Function clone
  //
  // Creates a new multi-method that fallsback to this one.
  //
  // :: @method => Unit -> method
  function clone() {
    var instance = method(dispatch)
    instance.fallback(this)
    return instance
  }
}
function method ( dispatch ) { var branches = [ ] var baseline = function ( a ) { throw noBranchFor ( a ) } var dispatchTable = new DispatchTable ( ) dispatch = dispatch || identity return makeMethod ( function ( ) { var value = dispatch . apply ( null , arguments ) var branch = dispatchTable . getBranch ( value ) . code || branchMatching ( value , branches ) . code || baseline return branch . apply ( null , arguments ) } ) // #### Function makeMethod // // Adds modification methods to a multi-method. // // :: method -> method function makeMethod ( f ) { f . when = when f . fallback = fallback f . remove = remove f . clone = clone return f } // ### Function when // // Adds a branch to a multi-method. // // :: @method => A, (B... -> C) -> method function when ( condition , f ) { if ( branchMatching ( condition , branches ) . code ) throw ambiguousBranch ( condition ) branches . push ( { condition : condition , code : f } ) dispatchTable . add ( condition , f ) return this } // ### Function fallback // // Adds a baseline branch, which is evaluated if no other branches // match a given dispatch value. // // :: @method => (A... -> B) -> method function fallback ( f ) { baseline = f return this } // ### Function remove // // Removes a branch from the multi-method. // // :: @method => A -> method function remove ( condition ) { branches = branches . filter ( function ( a ) { return ! equal ( condition , a . condition ) } ) return this } // ### Function clone // // Creates a new multi-method that fallsback to this one. // // :: @method => Unit -> method function clone ( ) { var instance = method ( dispatch ) instance . fallback ( this ) return instance } }
### Function method  Constructs a multi-method.  :: (A... -> B) -> method
### Function method Constructs a multi - method . :: ( A ... - > B ) - > method