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
|
from collections.abc import Callable
from typing import TypeVar, Any, ParamSpec
from ._const import CRU_PLACEHOLDER
T = TypeVar("T")
R = TypeVar("R")
R1 = TypeVar("R1")
P = ParamSpec("P")
P1 = ParamSpec("P1")
class RawFunctions:
@staticmethod
def none(*_v, **_kwargs) -> None:
return None
@staticmethod
def true(*_v, **_kwargs) -> True:
return True
@staticmethod
def false(*_v, **_kwargs) -> False:
return False
@staticmethod
def identity(v: T) -> T:
return v
@staticmethod
def only_you(r: T, *_v, **_kwargs) -> T:
return r
@staticmethod
def equal(a: Any, b: Any) -> bool:
return a == b
@staticmethod
def not_equal(a: Any, b: Any) -> bool:
return a != b
@staticmethod
def not_(v):
return not v
class MetaFunction:
@staticmethod
def bind(f: Callable[P, R], *bind_args, **bind_kwargs) -> Callable[P1, R1]:
def bound(*args, **kwargs):
popped = 0
real_args = []
for a in bind_args:
if a is CRU_PLACEHOLDER:
real_args.append(args[popped])
popped += 1
else:
real_args.append(a)
real_args.extend(args[popped:])
return f(*real_args, **(bind_kwargs | kwargs))
return bound
@staticmethod
def chain(*fs: Callable) -> Callable:
if len(fs) == 0:
raise ValueError("At least one function is required!")
rf = fs[0]
for f in fs[1:]:
def n(*args, **kwargs):
r = rf(*args, **kwargs)
r = r if isinstance(r, tuple) else (r,)
return f(*r)
rf = n
return rf
@staticmethod
def chain_single(f: Callable[P, R], f1: Callable[P1, R1], *bind_args, **bind_kwargs) -> \
Callable[
P, R1]:
return MetaFunction.chain(f, MetaFunction.bind(f1, *bind_args, **bind_kwargs))
convert_r = chain_single
@staticmethod
def neg(f: Callable[P, bool]) -> Callable[P, bool]:
return MetaFunction.convert_r(f, RawFunctions.not_)
# Advanced Function Wrapper
class CruFunction:
def __init__(self, f):
self._f = f
@property
def f(self) -> Callable:
return self._f
def bind(self, *bind_args, **bind_kwargs) -> "CruFunction":
self._f = MetaFunction.bind(self._f, *bind_args, **bind_kwargs)
return self
def chain(self, *fs: Callable) -> "CruFunction":
self._f = MetaFunction.chain(self._f, *fs)
return self
def chain_single(self, f: Callable[P, R], f1: Callable[P1, R1], *bind_args,
**bind_kwargs) -> "CruFunction":
self._f = MetaFunction.chain_single(self._f, f, f1, *bind_args, **bind_kwargs)
return self
def convert_r(self, f: Callable[P, R], f1: Callable[P1, R1], *bind_args,
**bind_kwargs) -> "CruFunction":
self._f = MetaFunction.convert_r(self._f, f, f1, *bind_args, **bind_kwargs)
return self
def neg(self) -> "CruFunction":
self._f = MetaFunction.neg(self._f)
return self
def __call__(self, *args, **kwargs):
return self._f(*args, **kwargs)
@staticmethod
def make_chain(*fs: Callable) -> Callable[P, R1]:
return CruFunction(MetaFunction.chain(*fs))
class WrappedFunctions:
none = CruFunction(RawFunctions.none)
true = CruFunction(RawFunctions.true)
false = CruFunction(RawFunctions.false)
identity = CruFunction(RawFunctions.identity)
only_you = CruFunction(RawFunctions.only_you)
equal = CruFunction(RawFunctions.equal)
not_equal = CruFunction(RawFunctions.not_equal)
not_ = CruFunction(RawFunctions.not_)
|