Skip to content

Comment on Show HN: multimethod.js - a Clojure-inspired multimethod library for JavaScriptparent

Comments

While fib is a good example of concisely illustrating the control flow of a multimethod, it is a bad example of where it makes sense to use a multimethod. What is interesting about a multimethod is you can change your dispatch logic and bind new cases well after your multimethod function is constructed. In situations like fib where you know every case you need to handle up front you should certainly use 'switch'.

To illustrate this flexibility in the context of fib, multimethod.js, and CoffeeScript:

   > fib = multimethod()
           .when(0, 0)
           .when(1, 1)
           .default (n) -> fib(n)
   > fib 20
   6765

   > fib.dispatch (n) -> n.numberVal or n
   > fib 20
   6765

   > fib { numberVal: 20 }
   6765

   > fib.when 2, 1
   > fib.when 3, 2
   > fib 20
   6765 (now "optimized" with fewer recursive calls than before)

Could you comment on a good use-case for this? A time when it would actually be better to construct a switch block dynamically vs all at once.

Great question, probably worthy of its own post. Rather than trying to think of times you want to construct switch statements dynamically, try to think of times you'd like to specialize how a generic function call will respond to arguments it may not even know about.

In object-oriented programming, you can define a base class "Animal" with a method "makeNoise" and subclasses with a method "makeNoise" with that will return "bark" if you call a Dog's makeNoise or "meow" if you call a Cat's. When you first defined the Animal's "makeNoise" method you didn't need to know how anything about the subclasses that would eventually implement it. Your algorithms could depend on "makeNoise" returning the noise specific to the animal in question.

Multimethods are a functional approach to polymorphism without a class/prototype hierarchy. The second example in the post shows how you might implement a multimethod that calculates the area of shapes. Perhaps a separate module introduces new kinds of shapes (like new kinds of subclasses in OO). These shapes can register their area implementations with the 'area' multimethod. Other algorithms that use the 'area' multimethod will now be able to operate on these new kinds of shapes. Multimethods provide a means to polymorphism while keeping data and functionality decomposed.

Like swannodette says more beautifully and concisely, though, it's an even more generic/flexible dispatch than thinking in terms of OO polymorphism.

The whole point of multimethods is open extension not pattern matching. Many programming languages let you dispatch only on the first argument - the instance. multimethods generalize this.

So the use-case is the same use-case as defining classes, except we have a lot more flexibility.

AboutSource Built by g1lg1l

Hackerly is an independent reader for Hacker News, built on the public HN API. Not affiliated with Y Combinator.