Now I have made it:
In[38]: C / list / map % (lambda x: x*2) @ range(1,5)
Out[38]: [2, 4, 6, 8]
work
So, /
is composition , %
is partial (nice trick) and @
is applying.
buyoperations = C / collections.OrderedDict / map % (lambda x: (x[0],x)
/ self.get_buy_operations_with_adjusted / sorted @ items
^ Actually similar thing worked. Pretty cool.
&
is partial but in lower precedence .
^
is applying with lower precedence
So,
In [109]: C / list/ zip & C / list @ range(5) ^ [4,8,9,10,11]
Out[109]: [(0, 4), (1, 8), (2, 9), (3, 10), (4, 11)]
is
list ( partial ( zip , ( list(range(5)) )) ( [4,8,9,10,11]) )
The full code:
from typing import Callable, TypeVar
from typing_extensions import ParamSpec
T = TypeVar('T')
P = ParamSpec('P')
Q = ParamSpec('Q')
U = TypeVar('U')
from typing import Generic
class CInst(Generic[P,T]):
def __init__(self,func :Callable[P,T]):
self.func=func
def __truediv__(self,other :Callable[Q,U]) -> CInst[Q,T] :
def inner(*args: Q.args, **kwargs: Q.kwargs) -> T:
return self.func(other(*args,**kwargs))
return CInst(inner)
def __and__(self,other):
return self.__mod__(other)
def __xor__(self,other):
return self.__matmul__(other)
def __call__(self,*args: P.args, **kwargs: P.kwargs) -> T:
return self.func(*args,**kwargs)
def __matmul__(self,other) -> T:
if (type(other) == tuple):
return self.func(*other)
elif (type(other) == dict):
return self.func(**other)
else:
return self.func(other)
def __mod__(self, other):
if (type(other) == tuple):
f= partial(self.func,*other)
elif (type(other) == dict):
f= partial(self.func,**other)
else:
f=partial(self.func, other)
return CInst(f)
class CSimpInst(CInst):
def __init__(self):
self.func = None
def __truediv__(self,other :Callable[Q,U]) -> CInst[Q,U] :
return CInst(other)
def __call__():
raise NotImplemented()
C=CSimpInst()
A low precedence right to left operator could have been nice…
Full code with currying is at https://github.com/eyalk11/compare-my-stocks/blob/master/src/compare_my_stocks/common/composition.py