Pipe method: Do you think something like this should be in standard library?

I wanted something similar to a pipe-forward operator, so I created a very simple pipe method. It is very simple and useful, I think it would be nice to have it built-in.

There's already a dbg! macro that does this.

Did you confuse something? Or was I not clear enough? How does one use dbg! to pipe values?

I've meant for pipe(log).

For more general piping, see:

This is very similar to Kotlin's let and run extension functions.

I think this .pipe() method somehow needs to prove itself, maybe if it proves to be popular and significantly useful in some parts of the ecosystem?

Just so I get this correctly, since you didn't mention it, this is about allowing to write x.pipe(f) instead of f(x), right?

pipe is useful enough in languages such as F# and LISP that they have pipe operator/macro.

yes

This looks like the apply crate. While I like it, I don't think it has seen enough use to justify inclusion in the standard library.

1 Like

F# and lisp are also both functional languages, and rust is not, so not all idioms will translate nicely. For example, pipe combines cleanly with an operator based map / fold / etc, but how would it interact with the method based version that rust has on iterators?

This seems like an excellent idea to prove out in an external crate, using generic traits or macros. If the community finds it generally beneficial, it may be worth introducing custom syntax for it.

1 Like

My personal experience and understanding of other languages is that idioms such as currying, partial application, pipe operators, and the endless array of other irregular application operators are far, far more useful in "pure functional languages" where it's actually possible to implement them in a fully generic way on any function and any arguments.

In Rust, I'm fairly sure this can never be as generic or as useful as it is in those pure functional languages because Rust doesn't have a GC, has both value and reference types, has both mutable and immutable types, and has the whole lifetime and ownership system which affects what function signatures are legal to call where, among other things. For instance, in languages that have a GC, partial application is straightforward to implement for any function because you simply don't GC the applied arguments until after the function finally gets called. These are also a lot of the reasons why functions and closures are (and need to be) two completely different things in Rust (as well as C++), unlike pure functional Lisp/F#/etc and even "impure functional" languages like Javascript (is there a term for this?).

Or more simply: I don't think there's any way around the fact that a function call in Rust implies way more machinery, and often cannot be pulled apart into tiny independently executable pieces.

This still makes sense as a crate, and is likely useful when working with Rust code that is designed to be used with more functional idioms, but I just don't see this ever applying to the whole language enough to make sense in std.

10 Likes