
Pipe: Infix syntax for Python - toni
http://dev-tricks.net/pipe-infix-syntax-for-python
======
va1en0k
that's great! I always wanted something like this for Python

the problem is, I rarely feel like I can just use all these cool-syntax
libraries for production, since they don't add a lot of value. why do I need a
whole dependency dependency for something that just make one or two line more
readable?

I've written a syntax enhancer for PHP once, but it just added one feature
(array dereferencing) for a small but noticeable price of setting up; I never
considered it for production usage because there weren't enough features to
justify it. (CoffeeScript is an example of justifiable price for huge changes
and multiple ideas)

for personal just-for-fun projects (like solving project euler problems) it's
an awesome idea, though

~~~
ohyes
What I would like to see is a way to separate the the syntax of my code from
the semantics of my code. Ideally, my code editor should be able to take the
same piece of code and display it in a few different styles of syntax.

Then I could write my code in whatever syntax I want, and someone else could
flip a switch and change it into their preferred style of syntax.

I am honestly kind of puzzled as to why the concept of MVC disappears as soon
as we start writing coding tools. It seems that for any reasonable syntax that
you can write a parser for; it should also be possible to write an emitter
from an 'intermediate' syntax tree.

~~~
wladimir
I've also thought about this a few times. It's a pity that the SCID (Source
Code in Database) paradigm never really caught on. It would make things such
as representing the same code with different syntax (depending on user
preference) possible. It also makes refactoring/renaming easy as names are
only stored in one place, the rest refers to the same 'entity'. And you're
right, best practices for data formats are applied everywhere except for code.
After all, we're now in 2011 and still using old-fashioned text files.

------
jerf
ISTR that when people discussed various ways of overloading the pipe on
comp.lang.python back in the day, one thing you have to be careful of is that
the bitwise OR operator binds relatively weakly [1], and that can result in
some surprising behavior if you intuitively assign the | a precedence in your
head more suited to the behavior implemented here. In this particular case,
though, you probably wouldn't hit this problem very often... though in some
ways that can make the problem worse in its own way.

[1]: <http://docs.python.org/reference/expressions.html#summary>

~~~
VMG
This calls for allowing the entirely user-defined $-operator in python 4.

~~~
nyellin
What if two Python-based frameworks use $ for separate purposes? (e.g. Django
and NumPy)

------
riobard
The Fibonacci generator hurts my eyes! Here is a cleaner version.

    
    
        def fib():
            a, b    = 0, 1
            while True:
                yield a
                a, b    = b, a+b
    
    

Anyway, the order of the pipeline-like operation in Python sometimes really
bugs me. This one addresses part of it.

Recently I'm playing with Scala and it is really neat to do these stuff:

    
    
        // A lazy Fibonacci generator (a Scala Stream)
        lazy val fib: Stream[Long] = Stream.cons(0, Stream.cons(1, 
          fib.zip(fib.tail).map(pair => pair._1 + pair._2))) 
    
        fib filter(_ % 2 == 0) takeWhile (_ < 4000000) sum
        // 4613732

------
xtacy
A similar question was asked on Stackoverflow:

[http://stackoverflow.com/questions/4961017/clojure-style-
fun...](http://stackoverflow.com/questions/4961017/clojure-style-function-
threading-in-python)

Some answers seem enlightening:

    
    
      While I sympathize with the desire to create cool new language constructs (à la Lisp macros), it is not really the Python philosophy to do this:
    
        >>> import this
        [...]
        There should be one-- and preferably only one --obvious way to do it.

~~~
scott_s
Hey, fogus and btilly! Small world.

------
geophile
I have built something similar, coming at the problem from a different
direction. I wanted a Unix-style shell, but piping objects instead of strings.
For example, to sum x^2 from the command line, x = 0-9:

    
    
        bash$ osh gen 10 ^ f 'x: x**2' ^ red + $
    

^ is the pipe symbol, red means "reduce", $ means output, and f means apply
the given function.

The same capabilities are available as a Python library:

    
    
        from osh.api import *
        osh(gen(10), f(lambda x: x**2), red(lambda x, y: x + y), out())
    

or

    
    
        from osh.api import *
        osh(gen(10), f(lambda x: x**2), red('+'), out())
    

Osh can also run results on multiple hosts at once, in parallel, combining the
results in various ways; and integrates database access, piping tuples to and
from sql commands.

<http://geophile.com/osh>

~~~
iki23
Nice! Would deserve a github repository and keeping the pypi pakcage up-to-
date: <http://pypi.python.org/pypi/osh/>

~~~
geophile
Yes, the pypi entry is obsolete. For some reason, I get into some sort of
endless lost username/password purgatory whenever I try to register there. I
really should bring that up to date and put the package in github.

------
srean
Coincidentally enough I was looking at <http://code.google.com/p/python-
pipeline/> a few days ago. I fully expected them to be related by a fork, but
they dont seem to be. Python-pipeline executes a similar idea, but to infix-
chain iterators by way of generators. I guess some abstractions are just too
handy and useful and the chances are high that they will be
implemented/discovered independently. Pipe is just one of them.

------
d0m
Is there any helper function that convert existing functions into pipe's
style?

For instance:

    
    
      [1,2,3,4,5] | p(sum) 
    

where p would transform a def(seq, args, kwargs) to def(args,kwargs) and yield
the results?

Also, maybe:

    
    
      [1,2,3,4,5] >> sum
    

where that could be made automatically ?

~~~
heyitsnick
Keep in mind I have no idea how this magical code works. In fact I can't even
find the pipe character on my keyboard right now (I am copy and pasting it!).
But this seems to work:

    
    
        @Pipe
        def p(iterable, function, **kwargs):
            return function(iterable, **kwargs)
    
    
    
        In [3]: from pipe import *
        In [4]: [1,2,3,4,5] | p(sum)
        Out[4]: 15

~~~
jerf
"In fact I can't even find the pipe character on my keyboard right now"

On standard US keyboards, it's shift-backslash. YLMV.

~~~
heyitsnick
Ha thank you! I was typing the pipe character that's in the top left (alt gr +
`) that looked the same but is clearly a different character code. It's a bew
laptop with a new keyboard layout (US).

------
toni
github repo: <https://github.com/JulienPalard/Pipe/>

------
pepijndevos
Server is unresponsive. Maybe Coral will cache it sometime: <http://dev-
tricks.net.nyud.net/pipe-infix-syntax-for-python>

------
Fice
Reminds me of the threading macros (-> and ->>) from Clojure.

------
algorias
I wonder about the usefulness of this. Doesn't the python generator syntax
take care pretty well of most use-cases?

The first example could have been written like this, which is much simpler and
easier to read than both the prefix and infix versions:

sum(x * x for x in take_while(fib(), lambda x: x < 1000000) if x % 2)

~~~
lloeki
Inserting/disabling/swapping intermediate processing steps in between is
immensely easier with pipes, and you don't have to take care of balanced
parentheses.

------
biot
This reminds me of C#'s LINQ, but for Python... PLINQ?

[http://stackoverflow.com/questions/2062540/help-with-linq-
ex...](http://stackoverflow.com/questions/2062540/help-with-linq-
expression/2062565#2062565)

~~~
mmavnn
He mentions in the link that linq is an inspiration.

~~~
biot
Thanks, I had missed that in the comments.

------
zacharyvoase
I wrote a really similar library called Calabash a short while ago:
<https://github.com/zacharyvoase/calabash>

It’s all fully tested (python setup.py test), and I really like using it, but
I haven't done so in any large-ish production app yet because it just looks
completely different to the surrounding code. I _have_ used it with success in
some small scripts, but that's about it.

------
mmavnn
Very nice piece of sugar. Pipes are one of the things I love about f#, and
it's nice to have a quick and easy implementation for when I'm playing with
Django/App Engine.

------
aufreak3
Remove the pipe symbols and you get Forth syntax!

------
OnesimusUnbound
Nice source code, readable, and well documented. The author uses generators
when it makes sense.

I try to use ipython and pipe as my shell to see how it feels.

------
ivank
Possibly inspired by Pypes: <http://arvindn.livejournal.com/68137.html>

------
jhuni
Infix notation is more readable then poorly written "classical" prefix
notation.

------
moomba
Thats great, now if they added some of the other lisp features (macros, etc.)
I'd consider using python.

