Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

"The multimethod based design of the language"

I've only just started looking at Python, but I wasn't aware that it has true CLOS-style multimethods (or multiple dispatch). I know that there are ways you can add multiple dispatch to Python - but is it really accurate to say that the entire language has a design that is based on multiple dispatch?

Note that I'd be rather pleased to find that multimethods are an integral part of Python - they were one of my favourite features of CLOS and I still miss them.



I think "multiple dispatch" is the wrong word. "Dynamic dispatch" is a much better word for what Python does. It's a ridiculously powerful feature. It lets you wrap and replace functions at runtime, which gives you incredible monkey-patching power, which is important to people programming in the real world.

My favorite example: Suppose you have a naive O(2^n) recursive factorial() function. I can write "factorial = memoize(factorial)" and suddenly your recursive calls are to my new wrapped function, which references your original implementation inside its closure. This is only possible because your recursive implementation dynamically dispatches by name. I have turned your O(2^n) implementation into an O(n) implementation.

In an unsafe systems language like C, I would only be able to accomplish the same thing with some severe memory hacks, and in a language like Java or C# I don't know how I would be able to do the same thing without some serious involvement in runtime reflection tools, and maybe even some decompilation.


Sounds like the author of the article has no idea what a multimethod actually is then. :-)

Dynamic binding (in various forms) is arguably a pretty common language feature and generally nothing like as powerful as full multimethod implementations (let alone what is possible in CLOS).


> Sounds like the author of the article has no idea what a multimethod actually is then. :-)

The author (me) knows what multimethods are. I did however not find a better term to refer to the `iter(x)` -> `x.__iter__()` / `x.__getitem__()` concept.


I'm genuinely interested (not being snarky, honest) - could you explain why you think that expression has anything to do with multimethods? Like I said previously, I'm new to Python and I'm curious what that expression actually means.


> could you explain why you think that expression has anything to do with multimethods?

You can override the behavior of a function based on the types involved. For instance ``coerce(a, b)`` calls ``a.__coerce__(b)``. By overriding ``__coerce__`` for one type you can customize this.


Do you then have to have conditional code in a.__coerce__(b) to check the type of b and do the appropriate thing?


Basically yes. Although there are ways around it: http://www.artima.com/weblogs/viewpost.jsp?thread=101605


Thanks - that looks quite neat.

It seems to me there is a big difference between having a language that is truly based on multimethods and one where it is possible to implement multimethods fairly easily - from what I can see Python looks more like the latter.


That's called "Operator overloading" In this case the operator happens to look like a function, but it's not really any different than a + b -> a.__add__(b)


That's not just simple operator overloading. What mitsuhiko refers to is that iter() can iterate over an object not just when you implement __iter__() but also when you implement __getitem__() and __len__(), bool() has similar semantics as do several other functions and operators.


I've always heard them referred to as "Generic Functions", though the Wikipedia article is annoying opaque.

The important quality (in my practical understanding) is that a generic function's specialization is decoupled from the object system -- delegating to `x.__iter__()` doesn't require `x` inheriting a method from a parent; the process `iter(x)` uses to delegate might not even require any type information about `x` at all.


I like the Clojure form of multimethods a lot, it's even neater than CLOS. ( http://clojure.org/runtime_polymorphism )

C's dynamic dispatch hack isn't so terrible though--e.g. Microsoft has been doing it for a long time by sticking in a "useless" instruction at the start of every function. http://blogs.msdn.com/b/oldnewthing/archive/2011/09/21/10214...


Just for my own sanity - is "multimethod" another term for a form of pattern matching? Looking at the clojure code, it strongly reminds me of Haskell:

  encounter :: Species -> Species -> Result
  encounter (Bunny _) (Lion _) = RunAway
  encounter (Lion _) (Bunny _) = Eat
etc. Of course, pseudocode, syntax errors, whatever - but it looks to be the same idea?

edit - formatting


A key difference is that Haskell functions can only have one type signature, so you need to explicitly make "Bunny" and "Lion" data constructors for "Species". Multimethods operate on multiple types. You can fake multimethods in Haskell with multi-parameter type classes (with the language extensions to allow undecidable and overlapping instances).


I see. Thanks!


Rich Hickey actually commented on the difference between multimethods and pattern matching here: http://sadekdrobi.com/2009/05/27/multimethod-in-clojure-shou...

(Here's a pattern matching module I know of: https://github.com/brool/clojure-misc )


Does Clojure do method combinations? I was very fond of :before, :around and :after methods of the standard method combination and loved the fact that, if you really wanted to, you could have your own method combinations.

I know that "Aspect Oriented" tools support some of this stuff, but the last time I looked at those (admittedly a while ago) they seemed, at least for Java, to be pretty hacky. Not that I use Java anymore...


Clojure doesn't implement those out-of-the-box, but there might be a contrib module somewhere macroing it in... I think they're petty neat too.


> in a language like Java or C# I don't know how I would > be able to do the same thing without some serious > involvement in runtime reflection tools, and maybe > even some decompilation

You code to an interface and use an IoC container or dependancy injection framework to provide an instance of an object containing the required functionality.

So yeah, lots of reflection and tools :)


Here is how to do it in C#. http://diditwith.net/2007/02/12/UsingAutomaticMemoization.as... Pretty straight forward.


To some extent, Python's methods are a lot closer to multimethods than methods in other single-dispatch languages (largely because they have an explicit self).

This has the side-effect of making multiple dispatch work with the same syntax reasonably well http://en.wikipedia.org/wiki/Multiple_dispatch#Python


I had a similar response, reading the article. Cue Inigo Montoya voice: "You keep using that word. I do not think it means what you think it means."

http://www.youtube.com/watch?v=G2y8Sx4B2Sk


Bravo!


Well, since this is about people not using Python 3 yet...

It might amuse you to know that Perl 6, which isn't used either, has multi methods. :-)

Edit: Dynamic dispatch otoh is in most (all?) scripting languages.


Also Perl5 has multimethods via a Moose extension: https://metacpan.org/module/MooseX::MultiMethods


OK, thanks.

I must add, risking down votes in this thread, that it is fun to see Python people argue the practicality of Python 2 over the idealism/correctness of Python 3.

It is very similar to when Perl people argue that CPAN (better OO with Moose, better infrastructure for modules, etc) outweigh the emphasis on simple syntax in Python 2... :-)




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: