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. .. code:: python >>> 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 :func:`pipe ` it does the same thing, but has pretty good type inference. Or use manual annotations with ``Callable`` type. identity -------- We also ship :func:`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: - `Practical Usage of Identity Function `_ (JS) - `Using Identity Functions `_ (Scala) 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 :ref:`pipe`: .. code:: python >>> 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: .. code:: python >>> 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! .. code:: python 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. .. code:: python >>> 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 ------------- .. automodule:: returns.functions :members: