Ways to Dispatch#

You can add new methods to functions in a variety of ways. We list them all below.

Abstract Function Definitions#

A function can be abstractly defined using dispatch.abstract. When a function is abstractly defined, the function is created, but no methods are defined.

Example usage:

from numbers import Number

from plum import dispatch


@dispatch.abstract
def f(x: Number, y: Number):
    """Multiply two numbers."""


@dispatch
def f(x: float, y: float):
    """Multiply two floats."""
    return x * y


@dispatch
def f(x: int, y: int):
    """Multiply two ints."""
    return x * y

Then

>>> f.methods  # No implementation for `Number`s!
List of 2 method(s):
    [0] f(x: float, y: float)
        <function f at ...> @ ...
    [1] f(x: int, y: int)
        <function f at ...> @ ...

and calling help(f) produces

Help on Function in module __main__:

f(x: numbers.Number, y: numbers.Number)
    Multiply two numbers.

    ---------------------

    f(x: float, y: float)

    Multiply two floats.

    ---------------------

    f(x: int, y: int)

    Multiply two ints.

Extend a Function From Another Package#

Function.dispatch can be used to extend a particular function from an external package:

from package import f


@f.dispatch
def f(x: int):
    return "new behaviour"
>>> f(1.0)
'old behaviour'

>>> f(1)
'new behaviour'

Directly Invoke a Method#

Function.invoke can be used to invoke a method given types of the arguments:

from plum import dispatch


@dispatch
def f(x: int):
    return "int"


@dispatch
def f(x: str):
    return "str"
>>> f(1)
'int'

>>> f("1")
'str'

>>> f.invoke(int)("1")
'int'

>>> f.invoke(str)(1)
'str'

Define Multiple Methods at Once#

Dispatcher.multi can be used to implement multiple methods at once:

from typing import Union

from plum import dispatch


@dispatch.multi((int, int), (float, float))
def add(x: Union[int, float], y: Union[int, float]):
    return x + y
>>> add(1, 1)
2

>>> add(1.0, 1.0)
2.0

>>> try: add(1, 1.0)
... except Exception as e: print(f"{type(e).__name__}: {e}")
NotFoundLookupError: `add(1, 1.0)` could not be resolved.
Closest candidates are the following:
    add(x: int, y: int)
        <function add at ...> @ ...
    add(x: float, y: float)
        <function add at ...> @ ...