[Python-ideas] A more readable way to nest functions

zmo z+py+pyideas at m0g.net
Sun Jan 29 06:08:02 EST 2017


tl;dr: I agree with you, Steven, as proven by my former post, augmented
with the details of your reply: there's no advantage to add a new
operator and language construct for this use case.—

On Sun, Jan 29, 2017 at 01:30:13PM +1100, Steven D'Aprano wrote:
> On Sat, Jan 28, 2017 at 03:16:27PM +0100, zmo via Python-ideas wrote:
> > This idea sounds fun, so as a thought experiment why not imagine one
> > way of integrating it in what I believe would be pythonic enough.

> This idea is sometimes called "the Collection Pipeline" design pattern, 
> and is used in various command shells. Martin Fowler wrote about this 
> design pattern here:
> https://martinfowler.com/articles/collection-pipeline/
> and I wrote a recipe for it:
> https://code.activestate.com/recipes/580625-collection-pipeline-in-python/
> with a working, although basic, implementation.
>     print(list(map(float, filter(lambda n: 20 < n < 30, data))))
> […]
>     data | Filter(lambda n: 20 < n < 30) | Map(float) | List | Print

It's indeed an interesting tip and idea, and using the pipe is not a bad
idea as it's a good mnemonic for anyone who used a shell. About reading
order, I'm personally agnostic.

> (In principle, Python built-ins could support this sort of syntax so I 
> could write filter, map, list, print rather than custom versions Filter, 
> Map, etc. […] But for Python that would be a *major* change, and not one I 
> wish to propose. […])

Even as an external library, I would use that kind of syntax with
extreme care in python. As a python developer, one of the things I
really do enjoy is that any python code looks like a python code, and
that's because changing meaning of operators depending on the context is
discouraged.

Then, unlike Scala, C++ or Ruby, you never end up with the language
looking like a new DSL for each application or framework.

> > On Sat, Jan 28, 2017 at 12:41:24PM +0000, Ed Kellett wrote:
> > So, considering it's decided that the RHS is in charge of filling up all
> > the arguments of the LHS, 
> Is that actually decided?

it's not, it's part of the thought experiment of 'if we had such syntax',
how could we handle arguments?

> […] so either we have a new, parallel series of functions including
> Filter(...) or we write something like:
>     print XYZ list XYZ map XYZ lambda (f1, f2, arg): (f1, filter(f2, arg))(float, lambda n: 20 < n < 30, data)
> which is simply horrid. Maybe there could be a series of helper 
> functions, but I don't think this idea is workable. […]

> > […]
> > All in all, it can be a nice syntactic sugar to have which could make it
> > more flexible working with higher order functions, but it with the way
> > I'm suggesting to comply with python's arguments handling, it offers
> > little advantages when the RHS is not filling LHS arguments:
> > […]
> I think that "literal advantage" is being very kind. The best you can 
> say is that you save two pairs of parentheses at the cost of three 
> operators and moving arguments away from the functions that use them.

I said "little" not "literal" ☺ I started the whole reasoning trying to
be objective and figure how such a new syntax would be integrated in
python and what good use could be made of it. And in the end, I end up
with something that can offer a nice syntax for a very niche case, and
wouldn't be of much use most of the time.

The fact that it can be implemented with some operator overload, as you
nicely demonstrated just proves the fact further: this is not a good
idea.

> [...]
> > But then it would be just another way to introduce currying as a
> > language feature with an operator, so we should then just discuss on how
> > to add currying as a language syntax "by the book", but I'm pretty sure
> > that's a topic already discussed before I joined this list ;-)
> The easiest way to support currying, or at least some form of it, is:
>     from functools import partial as p
>     p(map, float)  # curries map with a single argument float
> which is not quite the map(float) syntax Haskell programmers expect, 
> but its not awful.

Indeed, I love having that available as a function! We could reopen the
debate as to whether we should implement currying into python, but since
my last post I've done a bit of searching, and found out it's been
discussed 14 years ago:

https://mail.python.org/pipermail/python-dev/2004-February/042668.html
https://www.python.org/dev/peps/pep-0309/

and a few discussions, implementations of (real) currying published more
recently:

https://mtomassoli.wordpress.com/2012/03/18/currying-in-python/
http://code.activestate.com/recipes/577928-indefinite-currying-decorator-with-greedy-call-and/
https://gist.github.com/JulienPalard/021f1c7332507d6a494b

I could argue that a nicer syntactic sugar and having it as a language
feature could help in having it supported in a more optimised fashion,
instead of using an added layer of abstraction. But, I won't ^^

Cheers,

-- 
zmo


More information about the Python-ideas mailing list