pub trait Pipe {
// Provided methods
fn pipe<R>(self, func: impl FnOnce(Self) -> R) -> R
where Self: Sized,
R: Sized { ... }
fn pipe_ref<'a, R>(&'a self, func: impl FnOnce(&'a Self) -> R) -> R
where R: 'a + Sized { ... }
fn pipe_ref_mut<'a, R>(
&'a mut self,
func: impl FnOnce(&'a mut Self) -> R
) -> R
where R: 'a + Sized { ... }
fn pipe_borrow<'a, B, R>(&'a self, func: impl FnOnce(&'a B) -> R) -> R
where Self: Borrow<B>,
B: 'a + ?Sized,
R: 'a + Sized { ... }
fn pipe_borrow_mut<'a, B, R>(
&'a mut self,
func: impl FnOnce(&'a mut B) -> R
) -> R
where Self: BorrowMut<B>,
B: 'a + ?Sized,
R: 'a + Sized { ... }
fn pipe_as_ref<'a, U, R>(&'a self, func: impl FnOnce(&'a U) -> R) -> R
where Self: AsRef<U>,
U: 'a + ?Sized,
R: 'a + Sized { ... }
fn pipe_as_mut<'a, U, R>(
&'a mut self,
func: impl FnOnce(&'a mut U) -> R
) -> R
where Self: AsMut<U>,
U: 'a + ?Sized,
R: 'a + Sized { ... }
fn pipe_deref<'a, T, R>(&'a self, func: impl FnOnce(&'a T) -> R) -> R
where Self: Deref<Target = T>,
T: 'a + ?Sized,
R: 'a + Sized { ... }
fn pipe_deref_mut<'a, T, R>(
&'a mut self,
func: impl FnOnce(&'a mut T) -> R
) -> R
where Self: DerefMut + Deref<Target = T>,
T: 'a + ?Sized,
R: 'a + Sized { ... }
}
Expand description
Provides universal suffix-position call syntax for any function.
This trait provides methods that allow any closure or free function to be placed as a suffix-position call, by writing them as
fn not_a_method(x: i32) -> u8 { x as u8 }
receiver.pipe(not_a_method);
Piping into functions that take more than one argument still requires writing a closure with ordinary function-call syntax. This is after all only a library, not a syntax transformation:
use tap::pipe::Pipe;
fn add(x: i32, y: i32) -> i32 { x + y }
let out = 5.pipe(|x| add(x, 10));
assert_eq!(out, 15);
Like tapping, piping is useful for cases where you want to write a sequence of processing steps without introducing many intermediate bindings, and your steps contain functions which are not eligible for dot-call syntax.
The main difference between piping and tapping is that tapping always returns the value that was passed into the tap, while piping forwards the value into the effect function, and returns the output of evaluating the effect function with the value. Piping is a transformation, not merely an inspection or modification.
Provided Methods§
sourcefn pipe<R>(self, func: impl FnOnce(Self) -> R) -> Rwhere
Self: Sized,
R: Sized,
fn pipe<R>(self, func: impl FnOnce(Self) -> R) -> Rwhere Self: Sized, R: Sized,
Pipes by value. This is generally the method you want to use.
Examples
use tap::pipe::Pipe;
fn triple(x: i32) -> i64 {
x as i64 * 3
}
assert_eq!(
10.pipe(triple),
30,
);
sourcefn pipe_ref<'a, R>(&'a self, func: impl FnOnce(&'a Self) -> R) -> Rwhere
R: 'a + Sized,
fn pipe_ref<'a, R>(&'a self, func: impl FnOnce(&'a Self) -> R) -> Rwhere R: 'a + Sized,
Borrows self
and passes that borrow into the pipe function.
Examples
use tap::pipe::Pipe;
fn fold(v: &Vec<i32>) -> i32 {
v.iter().copied().sum()
}
let vec = vec![1, 2, 3, 4, 5];
let sum = vec.pipe_ref(fold);
assert_eq!(sum, 15);
assert_eq!(vec.len(), 5);
sourcefn pipe_ref_mut<'a, R>(&'a mut self, func: impl FnOnce(&'a mut Self) -> R) -> Rwhere
R: 'a + Sized,
fn pipe_ref_mut<'a, R>(&'a mut self, func: impl FnOnce(&'a mut Self) -> R) -> Rwhere R: 'a + Sized,
Mutably borrows self
and passes that borrow into the pipe function.
Examples
use tap::pipe::Pipe;
let mut vec = vec![false, true];
let last = vec
.pipe_ref_mut(Vec::pop)
.pipe(Option::unwrap);
assert!(last);
Both of these functions are eligible for method-call syntax, and should not be piped. Writing out non-trivial examples for these is a lot of boilerplate.
sourcefn pipe_borrow<'a, B, R>(&'a self, func: impl FnOnce(&'a B) -> R) -> Rwhere
Self: Borrow<B>,
B: 'a + ?Sized,
R: 'a + Sized,
fn pipe_borrow<'a, B, R>(&'a self, func: impl FnOnce(&'a B) -> R) -> Rwhere Self: Borrow<B>, B: 'a + ?Sized, R: 'a + Sized,
Borrows self
, then passes self.borrow()
into the pipe function.
Examples
use std::borrow::Cow;
use tap::pipe::Pipe;
let len = Cow::<'static, str>::from("hello, world")
.pipe_borrow(str::len);
assert_eq!(len, 12);
sourcefn pipe_borrow_mut<'a, B, R>(
&'a mut self,
func: impl FnOnce(&'a mut B) -> R
) -> Rwhere
Self: BorrowMut<B>,
B: 'a + ?Sized,
R: 'a + Sized,
fn pipe_borrow_mut<'a, B, R>( &'a mut self, func: impl FnOnce(&'a mut B) -> R ) -> Rwhere Self: BorrowMut<B>, B: 'a + ?Sized, R: 'a + Sized,
Mutably borrows self
, then passes self.borrow_mut()
into the pipe
function.
use tap::pipe::Pipe;
let mut txt = "hello, world".to_string();
let ptr = txt
.pipe_borrow_mut(str::as_mut_ptr);
This is a very contrived example, but the BorrowMut
trait has almost
no implementors in the standard library, and of the implementations
available, there are almost no methods that fit this API.
sourcefn pipe_as_ref<'a, U, R>(&'a self, func: impl FnOnce(&'a U) -> R) -> Rwhere
Self: AsRef<U>,
U: 'a + ?Sized,
R: 'a + Sized,
fn pipe_as_ref<'a, U, R>(&'a self, func: impl FnOnce(&'a U) -> R) -> Rwhere Self: AsRef<U>, U: 'a + ?Sized, R: 'a + Sized,
Borrows self
, then passes self.as_ref()
into the pipe function.
sourcefn pipe_as_mut<'a, U, R>(&'a mut self, func: impl FnOnce(&'a mut U) -> R) -> Rwhere
Self: AsMut<U>,
U: 'a + ?Sized,
R: 'a + Sized,
fn pipe_as_mut<'a, U, R>(&'a mut self, func: impl FnOnce(&'a mut U) -> R) -> Rwhere Self: AsMut<U>, U: 'a + ?Sized, R: 'a + Sized,
Mutably borrows self
, then passes self.as_mut()
into the pipe
function.