Helper functions

We feature several helper functions to make your developer experience better.

compose

We also ship an utility function to compose two different functions together.

>>> from returns.functions import compose

>>> bool_after_int = compose(int, bool)
>>> assert bool_after_int('1') is True
>>> assert bool_after_int('0') is False

Composition is also type-safe. The only limitation is that we only support functions with one argument and one return to be composed.

Only works with regular functions (not async).

Warning

compose might fail to infer types for some functions. There are several problems: lambda and generic functions. In these cases mypy will fail to infer the types of the resulting function.

In this case, use pipe it does the same thing, but has pretty good type inference. Or use manual annotations with Callable type.

identity

We also ship returns.functions.identity() function to help you with the composition.

Identity function is a simple concept: it just returns its argument. If you wonder why do we need this function, please read below:

tap and untap

We need tap() function to easily compose values with functions that does not return. For example you sometimes need to print() values inside your pipe:

>>> from returns.functions import tap

>>> result = tap(print)(1)  # will print and return 1
1
>>> assert result == 1

You can also use the untap function to turn any function’s return type to None and still do its thing:

>>> from returns.functions import tap, untap

>>> result = untap(tap(print))(1)  # will print and return None
1
>>> assert result is None

This is also sometimes helpful for a typed function composition.

raise_exception

Sometimes you really want to reraise an exception from Failure[Exception] due to some existing API (or a dirty hack).

We allow you to do that with ease!

from returns.functions import raise_exception

def create_account_and_user(username: str) -> ...:
    """
    Creates new Account-User pair.

    Imagine, that you need to reraise ValidationErrors due to existing API.
    """
    return _validate_user(
        username,
    ).alt(
        # What happens here is interesting, since you do not let your
        # unwrap to fail with UnwrapFailedError, but instead
        # allows you to reraise a wrapped exception.
        # In this case `ValidationError()` will be thrown
        # before `UnwrapFailedError`
        raise_exception,
    )

def _validate_user(username: str) -> Result['User', ValidationError]:
    ...

Use this with caution. We try to remove exceptions from our code base. Original proposal is here.

not_

With not_ helper function we can easily deny a function returns. It supports functions with one or more arguments.

>>> from typing import List
>>> from returns.functions import compose, not_

>>> def is_even(number: int) -> bool:
...     return number % 2 == 0

>>> def number_is_in_list(number: int, list_: List[int]) -> bool:
...     return number in list_

>>> assert not_(is_even)(2) is False
>>> assert not_(number_is_in_list)(1, [2, 3, 4]) is True
>>> assert compose(int, not_(is_even))("1") is True

API Reference

identity(instance)[source]

Function that returns its argument.

>>> assert identity(1) == 1
>>> assert identity([1, 2, 3]) == [1, 2, 3]

This function is really helpful for some composition. It is also useful for “do nothing” use-case.

Parameters:

instance (TypeVar(_FirstType)) –

Return type:

TypeVar(_FirstType)

compose(first, second)[source]

Allows function composition.

Works as: second . first or first() |> second(). You can read it as “second after first”.

>>> assert compose(float, int)('123.5') == 123

We can only compose functions with one argument and one return. Type checked.

Parameters:
  • first (Callable[[TypeVar(_FirstType)], TypeVar(_SecondType)]) –

  • second (Callable[[TypeVar(_SecondType)], TypeVar(_ThirdType)]) –

Return type:

Callable[[TypeVar(_FirstType)], TypeVar(_ThirdType)]

tap(function)[source]

Allows to apply some function and return an argument, instead of a result.

Is useful for composing functions with side-effects like print(), logger.log(), etc.

>>> assert tap(print)(1) == 1
1
>>> assert tap(lambda _: 1)(2) == 2
Parameters:

function (Callable[[TypeVar(_FirstType)], Any]) –

Return type:

Callable[[TypeVar(_FirstType)], TypeVar(_FirstType)]

untap(function)[source]

Allows to apply some function and always return None as a result.

Is useful for composing functions that do some side effects and return some nosense.

Is the kind of a reverse of the tap function.

>>> def strange_log(arg: int) -> int:
...     print(arg)
...     return arg

>>> assert untap(strange_log)(2) is None
2
>>> assert untap(tap(lambda _: 1))(2) is None
Parameters:

function (Callable[[TypeVar(_FirstType)], Any]) –

Return type:

Callable[[TypeVar(_FirstType)], None]

raise_exception(exception)[source]

Helper function to raise exceptions as a function.

It might be required as a compatibility tool for existing APIs. That’s how it can be used:

>>> from returns.result import Failure, Result
>>> # Some operation result:
>>> user: Result[int, ValueError] = Failure(ValueError('boom'))

>>> # Here we unwrap internal exception and raise it:
>>> user.alt(raise_exception)
Traceback (most recent call last):
  ...
ValueError: boom
Parameters:

exception (Exception) –

Return type:

NoReturn

not_(function)[source]

Denies the function returns.

>>> from returns.result import Result, Success, Failure

>>> def is_successful(result_container: Result[float, int]) -> bool:
...     return isinstance(result_container, Success)

>>> assert not_(is_successful)(Success(1.0)) is False
>>> assert not_(is_successful)(Failure(1)) is True
Parameters:

function (Callable[[ParamSpec(_FuncParams)], bool]) –

Return type:

Callable[[ParamSpec(_FuncParams)], bool]

Do Notation Curry