Why are Clojure's multimethods better than 'if' or 'case' statements
Asked Answered
C

3

20

I've spent some time, trying to understand Clojure multimethods. The main "pro" multimethod argument, as far as I understand, is their flexibility, however, I'm confused with the argumentation of why multimethods are better than a simple if or case statement. Could someone, please, explain, where is the line between polymorphism and an overglorified case statement drawn?

EDIT: I should have been clearer in the question, that I'm more interested in comparison with the 'if' statement. Thanks a lot for the answers!

Cowboy answered 11/3, 2012 at 18:33 Comment(2)
Where is the line drawn between an if statement and an overglorified goto?Columbian
You may be interested https://mcmap.net/q/662151/-clojure-defprotocol-as-a-solution-to-the-expression-problem/625403, which isn't exactly a duplicate but is closely related.Phelan
L
21

The difference between multimethods and a big if-statement is that you need to modify the function that contains the case-statement to add cases to the if-statement. You can add a new method without touching the previously existing methods.

So if you define a multimethod inside your library and you want your users to be able to extend it for their own data types, that's no problem. If you had used an if-statement instead, it would be a big problem.

Lawsuit answered 11/3, 2012 at 19:42 Comment(1)
Ahh, that's indeed something I didn't understand well, thanks! So, the multimethods are not confined to the namespace where defmulti was declared?Cowboy
K
29

Say we have types A, B, C, D and E, and methods m1, m2, m3 taking single argument of the previous types. You can put them in a table like this:

   | A | B | C | D | E |
m1 |   |   |   |   |   |
m2 |   |   |   |   |   |
m3 |   |   |   |   |   |

The "switch" statement strategy is implementing one row of this table at a time. Suppose you add a new type F. You'll have to modify all implementations to support it.

The class-based polymorphism (C++, Java, etc.) allows you to implement a whole column instead. Adding a new type is thus easy, as you don't have to change the already defined classes. But adding a new method is hard, as you'll have to add it to all other types.

Multimethods allow you to implement single cells of the table independently of each other.

This flexibility is even greater if you have to dispatch on multiple arguments. Each new argument adds another dimension to this table, and both swich-based and class-based dispatches become very complex pretty quickly (c.f. Visitor pattern).

Note, that multimethods are actually even more generic than depicted, as you can dispatch on pretty much anything, not just on the types of the arguments.

Kab answered 11/3, 2012 at 19:43 Comment(0)
L
21

The difference between multimethods and a big if-statement is that you need to modify the function that contains the case-statement to add cases to the if-statement. You can add a new method without touching the previously existing methods.

So if you define a multimethod inside your library and you want your users to be able to extend it for their own data types, that's no problem. If you had used an if-statement instead, it would be a big problem.

Lawsuit answered 11/3, 2012 at 19:42 Comment(1)
Ahh, that's indeed something I didn't understand well, thanks! So, the multimethods are not confined to the namespace where defmulti was declared?Cowboy
A
2

ivant's answer above can be expanded by taking a look at this article . It does a good job of explaining the power of protocols. Think of multimethods as protocols with many dimensions.

Arawak answered 12/3, 2012 at 15:35 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.