Skip to content

Commit dc75a22

Browse files
committed
Closes #150
1 parent 9824fe1 commit dc75a22

File tree

6 files changed

+63
-66
lines changed

6 files changed

+63
-66
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ See (0Ver)[https://0ver.org/].
1010

1111
### Features
1212

13+
- **Breaking**: now `pipe()` does not require argument to be the first value,
14+
instead it is required to use: `pipe(f1, f2, f3, f4)(value)`
1315
- Adds `tap` function
1416
- Now `pipe` allows to pipe 8 steps
1517

docs/pages/pipeline.rst

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ Let's see an example.
2121
2222
from returns.pipeline import pipe
2323
24-
pipe(1, str, lambda x: x + 'b', str.upper)
24+
pipe(str, lambda x: x + 'b', str.upper)(1)
2525
# => Will be equal to: `1B`
2626
2727
There's also a way to compose containers together:
@@ -42,15 +42,19 @@ There's also a way to compose containers together:
4242
...
4343
4444
pipe(
45-
1, # we provide the initial value itself as a first argument
4645
regular_function, # composes easily
4746
returns_container, # also composes easily, but returns a container...
4847
# So we need to `box` the next function to allow it to consume
4948
# the container from the previous step.
5049
box(also_returns_container),
51-
)
50+
)(1) # we provide the initial value itself as a argument to `pipe(...)`
5251
# => Will return `Result[str, ValueError]` as declared in the last step
5352
53+
You might consider ``pipe()`` as :func:`returns.functions.compose` on steroids.
54+
The main difference is that ``compose`` takes strictly two arguments
55+
(or you might say that it has an arity of two),
56+
while ``pipe`` has infinite possible arguments.
57+
5458
See also :func:`returns.io.IO.lift` which is also extremely
5559
helpful for ``IO`` composition.
5660

returns/generated/pipe.py

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
from returns.functions import compose
66

77

8-
def _pipe(initial, *functions):
8+
def _pipe(*functions):
99
"""
1010
Allows to compose a value and up to 7 functions that use this value.
1111
@@ -17,12 +17,14 @@ def _pipe(initial, *functions):
1717
>>> from returns.pipeline import pipe
1818
1919
# => executes: str(float(int('1')))
20-
>>> pipe('1', int, float, str)
20+
>>> pipe(int, float, str)('1')
2121
'1.0'
2222
2323
See also:
2424
- https://stackoverflow.com/a/41585450/4842742
2525
- https://github.com/gcanti/fp-ts/blob/master/src/pipeable.ts
2626
2727
"""
28-
return reduce(compose, functions)(initial)
28+
def decorator(initial):
29+
return reduce(compose, functions)(initial)
30+
return decorator

returns/generated/pipe.pyi

Lines changed: 42 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -15,91 +15,76 @@ _T9 = TypeVar('_T9')
1515

1616
@overload
1717
def _pipe(
18-
p1: _T1,
19-
p2: Callable[[_T1], _T2],
20-
) -> _T2:
18+
p1: Callable[[_T1], _T2],
19+
p2: Callable[[_T2], _T3],
20+
) -> Callable[[_T1], _T3]:
2121
...
2222

2323

2424
@overload
2525
def _pipe(
26-
p1: _T1,
27-
p2: Callable[[_T1], _T2],
28-
p3: Callable[[_T2], _T3],
29-
) -> _T3:
26+
p1: Callable[[_T1], _T2],
27+
p2: Callable[[_T2], _T3],
28+
p3: Callable[[_T3], _T4],
29+
) -> Callable[[_T1], _T4]:
3030
...
3131

3232

3333
@overload
3434
def _pipe(
35-
p1: _T1,
36-
p2: Callable[[_T1], _T2],
37-
p3: Callable[[_T2], _T3],
38-
p4: Callable[[_T3], _T4],
39-
) -> _T4:
40-
...
41-
42-
43-
@overload
44-
def _pipe(
45-
p1: _T1,
46-
p2: Callable[[_T1], _T2],
47-
p3: Callable[[_T2], _T3],
48-
p4: Callable[[_T3], _T4],
49-
p5: Callable[[_T4], _T5],
50-
) -> _T5:
35+
p1: Callable[[_T1], _T2],
36+
p2: Callable[[_T2], _T3],
37+
p3: Callable[[_T3], _T4],
38+
p4: Callable[[_T4], _T5],
39+
) -> Callable[[_T1], _T5]:
5140
...
5241

5342

5443
@overload # noqa: WPS211
5544
def _pipe(
56-
p1: _T1,
57-
p2: Callable[[_T1], _T2],
58-
p3: Callable[[_T2], _T3],
59-
p4: Callable[[_T3], _T4],
60-
p5: Callable[[_T4], _T5],
61-
p6: Callable[[_T5], _T6],
62-
) -> _T6:
45+
p1: Callable[[_T1], _T2],
46+
p2: Callable[[_T2], _T3],
47+
p3: Callable[[_T3], _T4],
48+
p4: Callable[[_T4], _T5],
49+
p5: Callable[[_T5], _T6],
50+
) -> Callable[[_T1], _T6]:
6351
...
6452

6553

6654
@overload # noqa: WPS211
6755
def _pipe(
68-
p1: _T1,
69-
p2: Callable[[_T1], _T2],
70-
p3: Callable[[_T2], _T3],
71-
p4: Callable[[_T3], _T4],
72-
p5: Callable[[_T4], _T5],
73-
p6: Callable[[_T5], _T6],
74-
p7: Callable[[_T6], _T7],
75-
) -> _T7:
56+
p1: Callable[[_T1], _T2],
57+
p2: Callable[[_T2], _T3],
58+
p3: Callable[[_T3], _T4],
59+
p4: Callable[[_T4], _T5],
60+
p5: Callable[[_T5], _T6],
61+
p6: Callable[[_T6], _T7],
62+
) -> Callable[[_T1], _T7]:
7663
...
7764

7865

7966
@overload # noqa: WPS211
8067
def _pipe(
81-
p1: _T1,
82-
p2: Callable[[_T1], _T2],
83-
p3: Callable[[_T2], _T3],
84-
p4: Callable[[_T3], _T4],
85-
p5: Callable[[_T4], _T5],
86-
p6: Callable[[_T5], _T6],
87-
p7: Callable[[_T6], _T7],
88-
p8: Callable[[_T7], _T8],
89-
) -> _T8:
68+
p1: Callable[[_T1], _T2],
69+
p2: Callable[[_T2], _T3],
70+
p3: Callable[[_T3], _T4],
71+
p4: Callable[[_T4], _T5],
72+
p5: Callable[[_T5], _T6],
73+
p6: Callable[[_T6], _T7],
74+
p7: Callable[[_T7], _T8],
75+
) -> Callable[[_T1], _T8]:
9076
...
9177

9278

9379
@overload # noqa: WPS211
9480
def _pipe(
95-
p1: _T1,
96-
p2: Callable[[_T1], _T2],
97-
p3: Callable[[_T2], _T3],
98-
p4: Callable[[_T3], _T4],
99-
p5: Callable[[_T4], _T5],
100-
p6: Callable[[_T5], _T6],
101-
p7: Callable[[_T6], _T7],
102-
p8: Callable[[_T7], _T8],
103-
p9: Callable[[_T8], _T9],
104-
) -> _T9:
81+
p1: Callable[[_T1], _T2],
82+
p2: Callable[[_T2], _T3],
83+
p3: Callable[[_T3], _T4],
84+
p4: Callable[[_T4], _T5],
85+
p5: Callable[[_T5], _T6],
86+
p6: Callable[[_T6], _T7],
87+
p7: Callable[[_T7], _T8],
88+
p8: Callable[[_T8], _T9],
89+
) -> Callable[[_T1], _T9]:
10590
...

tests/test_pipeline/test_pipe.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,9 @@ class _UserProfile(object):
1616
def __call__(self, user_id: int) -> IO[Result[float, Exception]]:
1717
"""Fetches `UserProfile` TypedDict from foreign API."""
1818
return pipe(
19-
user_id,
2019
self._make_request,
2120
IO.lift(box(self._parse_json)),
22-
)
21+
)(user_id)
2322

2423
@impure
2524
@safe

typesafety/test_pipeline/test_pipe.yml

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,9 @@
33
main: |
44
from returns.pipeline import pipe
55
6-
reveal_type(pipe('1.0', float, int, bool)) # N: Revealed type is 'builtins.bool*'
6+
def convert(arg: str) -> float:
7+
return float(arg)
8+
9+
predefined = pipe(convert, int, bool)
10+
reveal_type(predefined) # N: Revealed type is 'def (builtins.str*) -> builtins.bool*'
11+
reveal_type(predefined('1.0')) # N: Revealed type is 'builtins.bool*'

0 commit comments

Comments
 (0)