The definition of multimethods presented here sounds suspiciously like ad-hoc polymorphism (or just overloading functions). It seems like the real difficulty is not in the concept but in the fact that I've now seen under three different names: multiple-dispatch, ad-hoc polymorphism and overloading. All but the last name seem complex; since I initially encountered the concept in Java as overloading, I never thought much about it.
Polymorphism based on types like this is something that statically typed languages are naturally good at. Looking at his example code, the trick to having this sort of code in dynamically typed Python is to introduce type annotations via decorators. You're doing the work of static typing for a fraction of the benefits.
Additionally, a statically typed language can take this concept even further. Haskell, for example, supports polymorphic functions like this very well using type classes. It even allows functions polymorphic on their return types--you can have a function `read` which takes a String and returns whatever. This means you can actually even have polymorphic constants--maxBound, for example, is the maximum value of whatever numerical representation it happens to be.
Overall, I think features like this make more sense in a statically typed language. They fit in--you're already specifying types everywhere--and can do more. However, it is interesting to see how you could accomplish something like this in a dynamically typed language.
I think you're getting distracted by the simplistic implementation presented here. multimethods are plenty powerful outside of static types - see CLOS, Clojure.
That said multimethods are a halfway step to predicate dispatch (this is mentioned in the article comments). With predicate dispatch you can get efficient dispatch on any interesting predicate - not just types - for example even?, odd?, structural matching, etc.
I think dynamic languages could benefit a lot from predicate dispatch.
Multimethods and overloading are completely different beasts, despite the syntactic similarity. Overloading is resolved at compile time by looking at the compile time types. Multimethods are dispatched at run time, by looking at the run time values. This makes overloading much less powerful. Multimethods are in fact problematic in statically typed languages; they are difficult (but not impossible) to type check.
Haskell is incompatible with OOP precisely because in Haskell everything is solved at compile-time. It's a different way of thinking that has both advantages and disadvantages, however you cannot move these concepts around easily (i.e. not many features in Haskell are compatible with Java or viceversa - for instance Microsoft tried implementing Haskell on top of .NET and simply gave up).
ad-hoc polymorphism
Yes it is - however, the difference between multi-methods and the polymorphism you get in Java (and Python) is that Java does runtime single-dispatch on the implicit parameter only, whereas a multimethod can do runtime dispatch on all parameters.
Plus, because it is at runtime, you can also give it conditions that aren't necessarily related to the types involved (depending on implementation of course).
Overall, I think features like this make more sense
in a statically typed language
You've got it backwards - a lot of the features in statically typed languages like Haskell or Java (e.g. overloading, since you mentioned it) are there to be a replacement for multi-methods. But the feature is so powerful that it hardly has any substitute (just like macros).
(in addition, it can be used to add type checking, and type-guided translation between json and python objects. it will also dispatch on "compound" types, like a list of integers).
I tend to prefer the (defmethod) form in CL. You get generic functions which can retrieve the function object specialized for the parameters with (find-method). You also get the auxiliary method goodness...
But the great thing with Python that the article shows is that there's probably a way you can get those things in Python too if you needed them.
So does Python have multiple dispatch or can you just implement it?
The challenge with expressive features like multimethods - does your language give you the tools not only to implement it, but to make it fast? This is yet another benefit of macros - the ability to add features like this and get good, perhaps even great, performance.
Since people are throwing out similar kinds of implementations, here's my pattern matching library (which is kind of the same thing as multimethods, but allowing more arbitrary matching than just based on type):
This does not compile as the compiler does not know which of the four versions it should call. As jules said overloading is resolved at compile time by looking at the compile time types. Multimethods are dispatched at run time, by looking at the run time values. In this case that would be the "int int" version.
The difference between multimethods and pattern matching is that pattern matching is usually "closed" (you can't add new clauses somewhere else), while multimethods allow you to extend the method with additional functionality.
Actually it's just checking the types at runtime, nothing much 'static' about it. This is pretty much the antithesis of duck typing, in fact. I could see it being useful, but I could also see it leading to confusion for people who expect Python's usual duck-typing behaviour when they pass their own types into a function.
Whoops you subclassed from a type for which this function has a multimethod defined? Gonna do something different.
On the other hand, in non-trivial programs there _are_ certainly occasions when you need to check the type, so using an elegant method like this isn't a bad compromise.
In this case, a switch statement wouldn't help because you're dealing with a bunch of boolean functions rather than a single value. If you were using something like typeof and switched on the type, a switch statement would make more sense. However, even that would be pretty tedious for code like this, I think.
In general though, I have no idea why Python doesn't have a switch or case statement of some sort.
It's not necessary. If there is long if/else chain in your code, something is probably wrong. In case of python (and other OO, weakly typed languages).
But my opinion is that it wouldn't hurt to have it there.
Any trivial example demonstrating how something like this works will seem obfuscatory, because examples are usually trivially solved with other approaches. But see the Expression Problem[1] for the deep problem.
Whether it's an appropriate solution depends on whether introducing new operations or new data types is more common; and where the modularity boundaries are. For example, what if the base class in the hierarchy doesn't have a method for the task you want to perform, and you can't add one because it belongs to third party code, and nor can you implement it appropriately for every descendant?
[+] [-] tikhonj|14 years ago|reply
Polymorphism based on types like this is something that statically typed languages are naturally good at. Looking at his example code, the trick to having this sort of code in dynamically typed Python is to introduce type annotations via decorators. You're doing the work of static typing for a fraction of the benefits.
Additionally, a statically typed language can take this concept even further. Haskell, for example, supports polymorphic functions like this very well using type classes. It even allows functions polymorphic on their return types--you can have a function `read` which takes a String and returns whatever. This means you can actually even have polymorphic constants--maxBound, for example, is the maximum value of whatever numerical representation it happens to be.
Overall, I think features like this make more sense in a statically typed language. They fit in--you're already specifying types everywhere--and can do more. However, it is interesting to see how you could accomplish something like this in a dynamically typed language.
[+] [-] swannodette|14 years ago|reply
That said multimethods are a halfway step to predicate dispatch (this is mentioned in the article comments). With predicate dispatch you can get efficient dispatch on any interesting predicate - not just types - for example even?, odd?, structural matching, etc.
I think dynamic languages could benefit a lot from predicate dispatch.
[+] [-] jules|14 years ago|reply
[+] [-] bad_user|14 years ago|reply
Plus, because it is at runtime, you can also give it conditions that aren't necessarily related to the types involved (depending on implementation of course).
You've got it backwards - a lot of the features in statically typed languages like Haskell or Java (e.g. overloading, since you mentioned it) are there to be a replacement for multi-methods. But the feature is so powerful that it hardly has any substitute (just like macros).[+] [-] andrewcooke|14 years ago|reply
(in addition, it can be used to add type checking, and type-guided translation between json and python objects. it will also dispatch on "compound" types, like a list of integers).
[+] [-] agentultra|14 years ago|reply
I tend to prefer the (defmethod) form in CL. You get generic functions which can retrieve the function object specialized for the parameters with (find-method). You also get the auxiliary method goodness...
But the great thing with Python that the article shows is that there's probably a way you can get those things in Python too if you needed them.
So does Python have multiple dispatch or can you just implement it?
[+] [-] swannodette|14 years ago|reply
[+] [-] ianb|14 years ago|reply
http://svn.colorstudy.com/home/ianb/recipes/patmatch.py
[+] [-] chadrs|14 years ago|reply
https://gist.github.com/1320421
Not to actually use, of course.
[+] [-] daenz|14 years ago|reply
[+] [-] antihero|14 years ago|reply
Ooh, C# style overloading.
[+] [-] Anchor|14 years ago|reply
[+] [-] unknown|14 years ago|reply
[deleted]
[+] [-] judofyr|14 years ago|reply
[+] [-] SammyRulez|14 years ago|reply
[+] [-] radarsat1|14 years ago|reply
Whoops you subclassed from a type for which this function has a multimethod defined? Gonna do something different.
On the other hand, in non-trivial programs there _are_ certainly occasions when you need to check the type, so using an elegant method like this isn't a bad compromise.
[+] [-] tikhonj|14 years ago|reply
[+] [-] mhb|14 years ago|reply
[+] [-] icebraining|14 years ago|reply
[+] [-] tikhonj|14 years ago|reply
In general though, I have no idea why Python doesn't have a switch or case statement of some sort.
[+] [-] rplnt|14 years ago|reply
But my opinion is that it wouldn't hurt to have it there.
[+] [-] adobriyan|14 years ago|reply
[+] [-] datashaman|14 years ago|reply
[+] [-] barrkel|14 years ago|reply
Whether it's an appropriate solution depends on whether introducing new operations or new data types is more common; and where the modularity boundaries are. For example, what if the base class in the hierarchy doesn't have a method for the task you want to perform, and you can't add one because it belongs to third party code, and nor can you implement it appropriately for every descendant?
[1] http://en.wikipedia.org/wiki/Expression_problem