You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
@@ -134,9 +134,9 @@ do(lambda e: print("hello 2 from 'do'"), # delayed because lambda e: ...
134
134
135
135
Unlike ``begin`` (and ``begin0``), there is no separate ``lazy_do`` (``lazy_do0``), because using a ``lambda e: ...`` wrapper will already delay evaluation of an item. If you want a lazy variant, just wrap each item (also those which don't otherwise need it).
Similar to Racket's [threading macros](https://docs.racket-lang.org/threading/). A pipe performs a sequence of operations, starting from an initial value, and then returns the final value:
139
+
Similar to Racket's [threading macros](https://docs.racket-lang.org/threading/). A pipe performs a sequence of operations, starting from an initial value, and then returns the final value. It's just function composition, but with an emphasis on data flow, which helps improve readability:
140
140
141
141
```python
142
142
from unpythonic import pipe
@@ -148,53 +148,56 @@ x = pipe(42, double, inc)
148
148
assert x ==85
149
149
```
150
150
151
-
This removes the need to read the source code backwards (compare `x = inc(double(42))`), while also making `x` have only a single definition at the call site.
152
-
153
151
Optional **shell-like syntax**, with purely functional updates:
154
152
155
153
```python
156
-
from unpythonic import piped, get
154
+
from unpythonic import piped, getvalue
157
155
158
-
x = piped(42) | double | inc |get
156
+
x = piped(42) | double | inc |getvalue
159
157
assert x ==85
160
158
161
159
p = piped(42) | double
162
-
assert p | inc |get==85
163
-
assert p |get==84# p itself is never modified by the pipe system
160
+
assert p | inc |getvalue==85
161
+
assert p |getvalue==84# p itself is never modified by the pipe system
164
162
```
165
163
166
-
Set up a pipe by calling ``piped`` for the initial value. Pipe into the sentinel ``get`` to exit the pipe and return the current value.
164
+
Set up a pipe by calling ``piped`` for the initial value. Pipe into the sentinel ``getvalue`` to exit the pipe and return the current value.
167
165
168
-
**Lazy pipes**for mutable initial values. Computation runs at ``get`` time:
166
+
**Lazy pipes**, useful for mutable initial values:
169
167
170
168
```python
171
-
from unpythonic importlazy_piped, get
169
+
from unpythonic importlazy_piped1, runpipe
172
170
173
171
lst = [1]
174
172
defappend_succ(l):
175
173
l.append(l[-1] +1)
176
-
return l #important, handed to the next function in the pipe
177
-
p =lazy_piped(lst) | append_succ | append_succ # plan a computation
174
+
return l #this return value is handed to the next function in the pipe
175
+
p =lazy_piped1(lst) | append_succ | append_succ # plan a computation
178
176
assert lst == [1] # nothing done yet
179
-
p |get # run the computation
177
+
p |runpipe# run the computation
180
178
assert lst == [1, 2, 3] # now the side effect has updated lst.
181
179
```
182
180
183
181
Lazy pipe as an unfold:
184
182
185
183
```python
184
+
from unpythonic import lazy_piped, runpipe
185
+
186
186
fibos = []
187
-
defnextfibo(state):
188
-
a, b = state
187
+
defnextfibo(a, b): # multiple arguments allowed
189
188
fibos.append(a) # store result by side effect
190
189
return (b, a + b) # new state, handed to next function in the pipe
191
-
p = lazy_piped((1, 1))# load initial state into a lazy pipe
190
+
p = lazy_piped(1, 1) # load initial state
192
191
for _ inrange(10): # set up pipeline
193
192
p = p | nextfibo
194
-
p |get # run it
195
-
print(fibos)
193
+
p |runpipe
194
+
assertfibos== [1, 1, 2, 3, 5, 8, 13, 21, 34, 55]
196
195
```
197
196
197
+
Both one-in-one-out (*1-to-1*) and n-in-m-out (*n-to-m*) pipes are provided. The 1-to-1 versions have names suffixed with ``1``. The use case is one-argument functions that return one value (which may also be a tuple or list).
198
+
199
+
In the n-to-m versions, when a function returns a tuple or list, it is unpacked to the argument list of the next function in the pipe. At ``getvalue`` or ``runpipe`` time, the tuple wrapper (if any) around the final result is discarded if it contains only one item. (This allows the n-to-m versions to work also with a single value, as long as it is not a tuple or list.)
0 commit comments