Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What are the benefits of using multimethods instead of cond in Clojure?

Why shouldn't multimethods in Clojure simply be replaced by cond expressions?

I was inspired to ask after looking at the simple examples of multimethods in Ch. 5 of Russ Olsen's book Getting Clojure.

In a reply to a similar question (Performance of multimethod vs cond in Clojure), user Daniel Compton says

Multimethods allow for open extension; others can extend your multimethod dispatching on arbitrary expressions. Cond expressions are closed to extension by others or even your own code.

But it's not at all clear to me what "open extension" and "closed to extension" mean in this context, since it seems to me that both multimethods and cond expressions can be edited or expanded quite easily.

So... why shouldn't multimethods in Clojure simply be replaced by cond expressions?

Or, equivalently, how or when exactly can using multimethods be better or more elegant than using cond?

like image 520
Asker Avatar asked May 28 '20 05:05

Asker


1 Answers

The key point here is "allow for open extension". Anyone can add new branches for your multimethods - a cond is hard-coded: new dispatches must be added to the cond code in place.

Let's say: you have some widgets and you want to draw them. The widgets have a :type and you want to dispatch how to draw on that type.

Writing a big cond for all the widgets you know about will work. But now for each new widget, you have to touch your cond source code and modify it. This can be perfectly fine for e.g. an actual application, that does not need extension.

Doing the same with multimethods, anyone can implement a draw for their widget. So you don't know all of them when writing your code. This makes it a way better (or even mandatory) approach for e.g. libraries.

Now imagine, that you have decided for the cond approach in a library you are writing. Anyone with a new widget now must write their own draw, dispatch for their draws first, then call your draw. Also they would have to make sure, their draw is called everywhere, where your draw was called to have it working (which often is just impossible in a clean way).

One popular example for a multimethod directly in the Clojure core is print-method. By that anyone can implement a "serialization" for their type and play nicely.

Other honourable mentions for examples to look at are clojure.test and integrant.

like image 186
cfrick Avatar answered Nov 12 '22 08:11

cfrick