Skip to content

Instantly share code, notes, and snippets.

@dyoder
Last active August 29, 2015 14:23
Show Gist options
  • Save dyoder/88215ab7b462908480e5 to your computer and use it in GitHub Desktop.
Save dyoder/88215ab7b462908480e5 to your computer and use it in GitHub Desktop.
multimethods in coffeescript
# Implementation...
dispatch = (method, ax) ->
match = { p: 0, f: method.default }
for [entry, f] in method.entries
if entry.length == ax.length
p = 0
for term, i in entry
if term == ax[i]
p += 3
else if term == ax[i].constructor
p += 2
else if term.constructor == Function && (ax[i] instanceof term)
p += 1
else
p = 0
break
if p >= match.p
match = { p, f }
if match.f.constructor == Function
match.f ax...
else
match.f
method = ->
m = -> dispatch m, arguments
m.entries = []
m.default = -> throw new TypeError "No method matches arguments."
m
define = (m, terms..., f) ->
m.entries.push [terms, f]
# Examples
fib = method()
define fib, 1, 1
define fib, Number, (n) -> n + (fib n - 1)
console.log fib 5
class A
class B extends A
a = new A
b = new B
foo = method()
define foo, A, -> "foo: A"
define foo, B, -> "foo: B"
define foo, A, B, -> "foo: A + B"
define foo, B, A, -> "foo: B + A"
define foo, a, b, -> "foo: a + b"
console.log foo b
console.log foo a, b
console.log foo b, a
try
console.log foo b, a, b
catch error
console.log error
# Some benchmarks
bench = (f) ->
start = Date.now()
f()
Date.now() - start
times = (n, f) -> f(i) for i in [0...n]
bar = method()
define bar, Number, Number, (n, m) -> n * m
baz = (n, m) -> n * m
console.log bench -> times 1e6, (n) -> bar n, n
console.log bench -> times 1e6, (n) -> baz n, n
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment