[Python-ideas] Function composition (was no subject)

Ron Adam ron3200 at gmail.com
Sun May 10 05:08:32 CEST 2015



On 05/09/2015 06:45 PM, Andrew Barnert via Python-ideas wrote:
> On May 9, 2015, at 08:38, Ron Adam<ron3200 at gmail.com>  wrote:
>> >
>> >
>> >
>> >On 05/09/2015 03:21 AM, Andrew Barnert via Python-ideas wrote:
>>>>> >>> >I suppose you could write (root @ mean @ (map square)) (xs),
>> >
>>> >>Actually, you can't. You could write (root @ mean @ partial(map,
>>> >>square))(xs), but that's pretty clearly less readable than
>>> >>root(mean(map(square, xs))) or root(mean(x*x for x in xs). And that's
>>> >>been my main argument: Without a full suite of higher-level operators
>>> >>and related syntax, compose alone doesn't do you any good except for toy
>>> >>examples.
>> >
>> >How about an operator for partial?
>> >
>> >          root @ mean @ map $ square(xs)

> I'm pretty sure that anyone who sees that and doesn't interpret it as
> meaningless nonsense is going to interpret it as a variation on Haskell and
> get the wrong intuition.

Yes, I agree that is the problems with it.

> But, more importantly, this doesn't work. Your square(xs) isn't going
> to  evaluate to a function, but to a whatever falling square on xs returns.
> (Which is presumably a TypeError, or you wouldn't be looking to map in the
> first place). And, even if that did work, you're not actually composing a
> function here anyway; your @ is just a call operator, which we already have
> in Python, spelled with parens.

This is following the patterns being discussed in the thread.  (or at least 
an attempt to do so.)

The @ and $ above would bind more tightly than the ().  Like the doc "." 
does for method calls.  But the evaluation is from left to right at call 
time.  The calling part does not need to be done at the same times the rest 
is done.  Or at least that is what I got from the conversation.

      f = root @ mean @ map & square
      result = f(xs)

The other examples would work the same.


>> >Actually I'd rather reuse the binary operators.  (I'd be happy if they were just methods on bytes objects BTW.)
>> >
>> >          compose(root, mean, map(square, xs))

> Now you're not calling square(xs), but you are calling map(square, xs),
> which is going to return an iterable of squares, not a function; again,
> you're not composing a function object at all.

Yes, this is what directly calling the functions to do the same thing would 
look like.  Except without returning a composed function.


> And think about how you'd actually write this correctly. You need to
> either use lambda (which defeats the entire purpose of compose), or partial
> (which works, but is clumsy and ugly enough without an operator or
> syntactic sugar that people rarely use it).

The advantage of the syntax is that it is a "potentially" (a matter of 
opinion) alternative to using lambda.  And apparently there are a few here 
who think doing it with lambda's or other means is less than ideal.


Personally I'm not convinced yet either.

Cheers,
   Ron



More information about the Python-ideas mailing list