I'm trying to implement a forward pipe functionality, like bash's |
or R's recent %>%
. I've seen this implementation https://mdk.fr/blog/pipe-infix-syntax-for-python.html, but this requires that we define in advance all the functions that might work with the pipe. In going for something completely general, here's what I've thought of so far.
This function applies its first argument to its second (a function)
def function_application(a,b):
return b(a)
So for example, if we have a squaring function
def sq(s):
return s**2
we could invoke that function in this cumbersome way function_application(5,sq)
. To get a step closer to a forward pipe, we want to use function_application
with infix notation.
Drawing from this, we can define an Infix
class so we can wrap functions in special characters such as |
.
class Infix:
def __init__(self, function):
self.function = function
def __ror__(self, other):
return Infix(lambda x, self=self, other=other: self.function(other, x))
def __or__(self, other):
return self.function(other)
Now we can define our pipe which is simply the infix version of the function function_application
,
p = Infix(function_application)
So we can do things like this
5 |p| sq
25
or
[1,2,3,8] |p| sum |p| sq
196
After that long-winded explanation, my question is if there is any way to override the limitations on valid function names. Here, I've named the pipe p
, but is it possible to overload a non-alphanumeric character? Can I name a function >
so my pipe is |>|
?
You can't really use |>|
in python, at the bare minimum you need | * > * |
where *
needs to be a identifier, number, string, or another expression.
Every line is a statement (simple or compound), a stmt
can be a couple of things, among them an expression, an expression is the only construct that allows the use of or operator |
and greater than comparison >
(or all operators and comparisons for that matter < > <= >= | ^ & >> << - + % / //
), every expression needs a left hand side and a right hand side, ultimatelly being in the form lhs op rhs
, both left and right hand side could be another expression, but the exit case is the use of an primary (with the exception of unnary -
, ~
and +
that need just a rhs
), the primary will boil down to an identifier, number or string, so, at the end of the day you are required to have an identifier [a-zA-Z_][a-zA-Z_0-9]*
along side a |
.
Have you considered a different approach, like one class that override the or operator instead of a infix class? I have a tiny library that does piping, might interest you
For reference, here is the full grammar:
https://docs.python.org/2/reference/grammar.html
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With