-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathpypes.py
More file actions
83 lines (69 loc) · 2.43 KB
/
pypes.py
File metadata and controls
83 lines (69 loc) · 2.43 KB
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
"""
Inspired by dplr's %>%, this project allows you to use functional pipes in
Python code. For example, instead of:
print(sum(map(int, input().split(","))))
you can write
-(O| input() | str.split | print)
You can also assign a pipe to a variable. The following code puts the sum into
the variable `foo` instead of printing it.
foo = -(O| input() | str.split | "," | (map, int) | sum)
"""
from functools import partial
from collections import deque
__all__ = ['O']
class Pipe:
"""
Pipe object
This object can be |'d with either a callable, a tuple, a list, or a dict.
A callable causes this callable to be added to the call stack. The other
datastructures prefill arguments of the callable:
- Tuples cause the first element to be interpreted as the callable, the
other ones as the first arguments. The pipe value gets added as a
parameter after this.
- Lists add arguments after the existing arguments, to the last added
callable.
- Dictionaries act like lists, but with keyword arguments.
"""
def __init__(self, new=True):
self.chain = deque()
self.val = None
self.new = new
def __or__(self, other):
if self.new:
return Pipe(new=False) | other
elif self.val is None:
self.val = other
elif isinstance(other, tuple):
# put argument _after_ these
# x | (map, len)
fn, *rest = other
self.chain.append(partial(fn, *rest))
elif callable(other):
self.chain.append(other)
elif isinstance(other, list):
# put argument _before_ these
# x | str.split | [","]
fn = self.chain[-1]
self.chain[-1] = lambda x: fn(x, *other)
elif isinstance(other, dict):
# put argument _before_ these
fn = self.chain[-1]
self.chain[-1] = lambda x: fn(x, **other)
# x | sum | {'start':0}
else:
# add a single argument
fn = self.chain[-1]
self.chain[-1] = lambda x: fn(x, other)
return self
def __neg__(self):
"""
Start the evaluation of the pipe.
"""
if self.val is None:
fn = self.chain.popleft()
self.val = fn()
while self.chain:
fn = self.chain.popleft()
self.val = fn(self.val)
return self.val
O = Pipe()