4 ms·
The definition of multimethods presented here sounds suspiciously like ad-hoc polymorphism (or just overloading functions). It seems like the real difficulty is
by tikhonj 15y ago
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.
- swannodette 15y agoI 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.
- jules 15y agoMultimethods 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.
- groovy2shoes 15y agoOverloaded functions are only partly resolved at compile time. The dispatch itself happens at run time using only one function parameter (single dispatch), which can be any of any compatible type. Single dispatch turns out to be super fast to implement with vtables; multiple dispatch tends to be slower, but it's sometimes worth it for the added expressiveness.
- barrkel 15y agoOverload resolution is entirely a compile-time task. But the method resolved may itself be virtual, and so use dynamic dispatch in its invocation. (Overload resolution is a pattern matching task, selecting a signature from a list of signatures, given a tuple of candidate value types[1]. It's not just used for invocation, but also when e.g. determining which overload of a function to assign to a function pointer.) [1] The set of value types is usually larger than the set of types available for use in signatures. For example, most static languages don't have a name for the type of the 'null' or 'nil' value, so you usually can't refer to it in a signature (and nor would it be particularly useful to do so).
- barrkel 15y agoThey are only completely different beasts if you think the distinction between compile time and run time is very important. That's not necessarily the case. There is the text of the program at one end, and pushing electrons at the other. At exactly which point this thing we call "compiling" occurred is just a detail that may or may not help us in other - typically human factor - goals. Multimethods, to a first approximation, is overload resolution at run time rather than compile time. They are not just syntactically similar; they are semantically similar too. Multimethods is the dynamic language analogue to overloading in static languages.
- riffraff 15y ago> Multimethods is the dynamic language analogue to overloading in static languages. This implies that multimethods are not possible in statically typed languages, which is trivially disproven by stuff like the Nice programming language. The difference between compile and run time is a red herring, since the actual distinction is between a statically _declared_ type and a dynamic type (which FWIW could be determined statically within AOT compilation).
- bad_user 15y agoHaskell 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).