/
pyfuncomp.py
101 lines (82 loc) · 2.71 KB
/
pyfuncomp.py
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
# -*- coding: utf-8 -*-
#http://github.com/si14/python-functional-composition
from functools import partial
import itertools
__all__ = ["_", "c", "composable"]
class ComposableFunction(object):
func = None
args = []
kwargs = {}
def _isSubst(self, x):
return isinstance(x, ToBeSubstituted)
def __init__(self, func, args=[], kwargs={}):
if hasattr(func, "__call__"):
self.func = func
elif isinstance(func, str):
self.func = lambda *x: eval(func % x)
else:
raise TypeError("Argument must be a string or callable")
self.args = args
self.kwargs = kwargs
def __call__(self, arg):
replacer = lambda x: arg if self._isSubst(x) else x
args = map(replacer, self.args)
kwargs = dict(zip(self.kwargs.keys(),
map(replacer, self.kwargs.values())))
if len(args) + len(kwargs) > 0:
return self.func(*args, **kwargs)
else:
return self.func(arg)
def __getitem__(self, arglist):
args = filter(lambda x: not isinstance(x, slice), arglist)
kwargs = dict([(x.start, x.end) for x in arglist if isinstance(x, slice)])
return ComposableFunction(self.func, args, kwargs)
def __lshift__(self, y):
f = lambda x: self(y(x))
return ComposableFunction(f)
def __rshift__(self, y):
f = lambda x: y(self(x))
return ComposableFunction(f)
def __getattr__(self, name):
if name == "map":
f = lambda x: map(self, x)
return ComposableFunction(f)
elif name == "filter":
f = lambda x: filter(self, x)
return ComposableFunction(f)
else:
raise AttributeError("Not implemented modifier %s" % name)
class ToBeSubstituted:
pass
#decorator
def composable(f):
return ComposableFunction(f)
#substitution mark
_ = ToBeSubstituted()
#transformer function
c = composable
if __name__ == "__main__":
@composable
def f1(x):
return x * 2
@composable
def f2(x):
return x + 3
@composable
def f3(x):
return (-1) * x
@composable
def f4(a):
return a + [0]
@composable
def sqrsum(x, y):
return x ** 2 + y ** 2
print f1(2) #4
print f2(2) #5
print (f1 << f2 << f1)(2) #14
print (f3 >> f2)(2) #1
print (f2 >> f3)(2) #-5
print (c(float) << f1 << f2)(4) #14.0
print (sqrsum[_, 1] << f1)(2) #17
print (sqrsum[_, _].map)([1, 2, 3, 4, 5]) #[2, 8, 18, 32, 50]
print (c(lambda x: x * 2).map >> c("[x * %s for x in %s]")[3, _])([1, 2, 3]) #[6, 12, 18]