File: functions.rst

package info (click to toggle)
python-returns 0.26.0-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 2,652 kB
  • sloc: python: 11,000; makefile: 18
file content (142 lines) | stat: -rw-r--r-- 3,868 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
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 <returns._internal.pipeline.pipe.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 <https://blog.bigbinary.com/2018/03/20/practical-usage-of-identity-function.html>`_ (JS)
- `Using Identity Functions <https://emilvarga.com/posts/2016/08/01/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 <https://github.com/dry-python/returns/issues/56>`_.


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: