Search code examples
pythonlibrariesdynamic-dispatch

Function pattern/predicate matching in Python


I'd like to be able to dispatch different implementations of a function, based not only on the type of the first parameter, but based on arbitrary predicates. Currently I have to do it like so:

def f(param):
    try:
        if param > 0:
            # do something
    except TypeError:
        pass
    try:
        if all(isinstance(item, str) for item in param):
            # do something else
    except TypeError:
        raise TypeError('Illegal input.')

Here's something in the spirit of what I'd like to be able to do:

@generic
def f(param):
    raise TypeError('Illegal input.')  # default

@f.when(lambda param: param > 0)
def f_when_param_positive(param):
    # do something

@f.when(lambda param: all(isinstance(item, str) for item in param))
def f_when_param_iterable_of_strings(param):
    # do something else

It is similar to Python 3's singledispatch, however singledispatch only supports dispatch on types, not on arbitrary predicates.

TL;DR: Is there a library that allows a predicate-based dispatch of a function based on arbitrary predicates (not only the parameter's type)?


Solution

  • Thanks to the repliers. After asking this question it seemed there was no existing module that does exactly this. So I wrote my own :) It is inspired by @Elazar's suggestion.

    Please feel free to check it out. It's on PyPI and you can install it using:

    pip install genericfuncs
    

    It's also hosted on GitHub and I plan to continue development and add features while trying to keep the API simple. Contributions are welcome.