First of all, I tried to read through the proposal but many parts were off-topic to me or irrelevant for my reply so sorry if I’m repeating what has already been said or argued against.
I voted “no” because there already exists a package for that, namely pydash
which is the Python equivalent of the Javascript lodash
package, which essentially has many utilities that users want despite not being part of the standard JS library. The helper in question is Method Chaining - pydash 8.0.5 documentation . The doc is a bit simple but you can essentially invoke any pydash methods on an object, effectively making a pipeline. There is an initial value that is used but it can be reused with .plant()
so the laziness you wanted is here. It’s not exactly a pure pipe as you had but I think it’s boils down to the same idea.
A simpler pipeline is exposed through funcy.compose
and funcy.rcompose
( Functions — funcy 2.0 documentation ) so I honestly don’t think we need to incorporate the pipeline into the standard library.
In Java, we have a similar interface, though only on sequences, named the Stream API. It’s not using pipes but is based on method chaining, which is essentially what a pipe could achieve without having to implement the methods on the objects themselves. It’s mimicking what we can in JavaScript with .map()
etc, but not everyone in the Java community is well-versed in functional programming so I don’t think it’s that used (and last time I checked, well it was some time ago, it’s slower than plain for-loops). I personally used it in my projects, but plain loops or separate functions are usually better, both for readability and debugging.
While PHP does now have a pipeline operator, Javascript still doesn’t and Javascript has much more functional programming than PHP. The rationale behind Javascript’s pipeline operator ( proposal-pipeline-operator/README.md at main · tc39/proposal-pipeline-operator · GitHub ) is that jQuery provides method chaining but only for methods that are implemented, thereby making it sometimes not that useful, and lacks support for await
and yield
constructions for instance. I don’t know why PHP actually wanted to add this to their langage when JS still hadn’t.
The rationale for JS stems from real-world examples that can be found in React, e.g.:
// https://github.com/facebook/react/blob/12adaffef7105e2714f82651ea51936c563fe15c/scripts/jest/jest-cli.js#L295-L303
console.log(
chalk.dim(
`$ ${Object.keys(envars)
.map(envar =>
`${envar}=${envars[envar]}`)
.join(' ')
}`,
'node',
args.join(' ')));
Using pipe operators would make it
Object.keys(envars)
.map(envar => `${envar}=${envars[envar]}`)
.join(' ')
|> `$ ${%}`
|> chalk.dim(%, 'node', args.join(' '))
|> console.log(%);
In Python, I don’t think I’ve ever seen a production code where we really have multiple nested calls without intermediate variables or a comment, or intermediate functions. So, unless there are popular libraries that could benefit from either a pipe operator, I don’t think it warrants its addition to the standard library for now.
Now, let’s discuss about the pipe object in this proposal. If I were to choose, I would rather have a pipe operator than a pipe object. A pipe object is essentially a huge composed function. However, it could lack support for await
and that could also be a huge no. The proposal doesn’t explain how await my_func()
could work. This would still need something like this:
async def my_func(x):
y = do(x)
z = await async_then(y)
return z
Similarly, it’s not possible to use yield
constructions that regular functions allow. On the other hand, a pipe operator could solve at the interpreter level the problem of async
and yield
by essentially creating the equivalent function (e.g., my_func = do |> await async_then
would be equivalent to the above explicit function definition). Since the current proposal lacks support for async and intermediate yield
, I’m against it (well, mostly because it doesn’t support async well; yield
is rarer).