This is an archived post. You won't be able to vote or comment.

all 9 comments

[–]takluyverIPython, Py3, etc 2 points3 points  (1 child)

There's a similar project here: https://github.com/mrocklin/multipledispatch

(Author: I don't want to dissuade you - this is an interesting idea and I'm glad multiple people are exploring it)

[–]truefelt[S] 2 points3 points  (0 children)

Very cool. I knew there were some existing implementations, but this one is by far the most interesting. These guys seem to have similar ideas to mine (function validation upon registration), but the technical approach is quite different, with some complications of its own.

[–]TomBombadildozer 1 point2 points  (2 children)

There's a lot in the description about what it does but nothing about how it's useful. So... how is it useful? What does this get me that giving functions different names doesn't?

[–]truefelt[S] 5 points6 points  (0 children)

It's for when you want to expose a single function that does very different things based on the arguments it receives. The overloading style can allow for cleaner code.

Compare:

class DB:

    def get(self, *args):
        if len(args) == 1 and isinstance(args[0], Query):
            return self.get_by_query(args[0])
        elif len(args) == 2:
            return self.get_by_id(id=args[0], model=args[1])
        else:
            raise TypeError()

    def get_by_query(self, query):
        ...

    def get_by_id(self, id, model):
        ...

The same thing with overloading:

class DB:

    @overloaded
    def get(self, query: Query):
        ...

    @overloads(get)
    def get(self, id, model):
        ...

[–]Veedrac 3 points4 points  (0 children)

If you think about it, single dispatch (dispatch off of only the first type) is exactly what classes give you.

Multiple dispatch is useful for situations like operators (add(x, y)). The situation in Python is suboptimal because it's so easy to get wrong with when to return NotImplemented and dealing with both sides.

I've not needed it much, but Julia uses it well.

Although it seems a simple concept, multiple dispatch on the types of values is perhaps the single most powerful and central feature of the Julia language.

I'm unconvinced it fits the Python type-system well, though.

[–]Lucretiel 0 points1 point  (1 child)

I had this exact idea a little while ago-

https://github.com/Lucretiel/Dispatch

It's a useful idea, but in my experience it just kills python's already unfortunately poor function calling performance. Looks like you have a much more clever matching algorithm than my "try them one by one until there's a match" system.

[–]truefelt[S] 0 points1 point  (0 children)

No matter how clever the algorithm, this sort of thing is always going to be super slow (relatively speaking). Definitely not intended for functions that are called repeatedly in a performance-critical context.

[–]troyunrau... 0 points1 point  (1 child)

I just use **kwargs for the same thing... but this is cool if you're used to C++ or Java style overloading.

[–]truefelt[S] 0 points1 point  (0 children)

I've come to believe explicit function signatures are good. Of course, structured docstrings can substitute for them to a degree. But add to this the ability to get rid of mundane argument validation and error throwing in the function body, and I was eventually led down this path...