`functools.pipe` - Function Composition Utility

pipe is not a def/lambda alternative in the same way that partial is not.

Same as partial, it is a functional utility, which takes callables as arguments and returns a derivative result.

pipe, same as partial compared to def, although superficially seems to do the same thing, has a different role and advantages in functional programming.


There is no single pressing problem which this solves, but the case that I have gathered judges the combined benefit of this in various places in relation to minimal cost of such.

Benefits are (but not limited to):

  1. Benefit of functional utility, which has already been implemented in many libraries. Such cases have higher significance compared to plain use cases as this indicates that many people have been abstracting this themselves. Many different use cases and 3rd party implementations have been mentioned in this thread and the amount of it is considerable.
  2. Where appropriate (in functional context) this would be a replacement for lambda as it would offer serializability for cases of ad-hoc constructed callable arguments (e.g. predicates) and similar cases where building blocks of functional design need to be persistent.
  3. Would cover “piping” appetite to a sufficient degree by providing performant, robust utility to build upon.

The cost of such is minimal.

It has no implications on other parts of the library. It would be among the simplest utilities in functools.

Arguably it encourages some bad practices, but it is no more than partial does and this cost is minimal in the light of the full picture.

There exist very many packages. Ones that are solely focused on this and those that implement this as internal utility. This is the point - among various functional utilities, this one might be common enough to pull into standard library removing repetition and providing robust and performant implementation.

A method is a function bound to an object, so it is a kind of function (callable also), and we are talking about a proposal for function composition. It is therefore, in my view, very relevant. Conceptually, and taking a broad view of piping, and also remembering that function composition will usually involve some initial data, I don’t see any difference.

I am convinced one should not be forced to name intermediate results in a chain of operations. Today, assigning to a temporary variable is not a solution since it is incompatible with static type checking.

The functools.pipe goes in that direction and I support it as long as we make it type-safe, even if it is with the workaround that works up to functions of a maximum arity.

1 Like