Skip to content

Instantly share code, notes, and snippets.

@oteku
Created April 7, 2019 22:19
Show Gist options
  • Save oteku/a4a8883671610e02cf2103569c9cc994 to your computer and use it in GitHub Desktop.
Save oteku/a4a8883671610e02cf2103569c9cc994 to your computer and use it in GitHub Desktop.
Rust composition vs pipe vs pipe operator
// function used to compose
fn compose_two<A, B, C, G, F>(f: F, g: G) -> impl Fn(A) -> C
where
F: Fn(A) -> B,
G: Fn(B) -> C,
{
move |x| g(f(x))
}
fn pipe_two<A, B, F>(a : A, f: F) -> B
where
F: Fn(A) -> B,
{
f(a)
}
// composition macro
macro_rules! compose {
( $last:expr ) => { $last };
( $head:expr, $($tail:expr), +) => {
compose_two($head, compose!($($tail),+))
};
}
// pipe macro
macro_rules! pipe {
( $last:expr ) => { $last };
( $head:expr, $($tail:expr), +) => {
pipe_two($head, compose!($($tail),+))
};
}
use std::ops::Shr;
use std::fmt;
// Need a wrapper to implement pipe operator
struct Wrapped<T>(T);
// Implement pipe operator ('Shr' is '>>')
impl<A, B, F> Shr<F> for Wrapped<A>
where F: FnOnce(A) -> B
{
type Output = Wrapped<B>;
fn shr(self, f: F) -> Wrapped<B> {
Wrapped(f(self.0))
}
}
// Implement display for i32 exemple
impl fmt::Display for Wrapped<i32> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}", self.0)
}
}
fn main() {
let add = |x| x + 2;
let multiply = |x| x * 2;
let divide = |x| x / 2;
let composed_function = compose!(add, multiply, divide);
println!("Result is {}", composed_function(10));
println!("Result is {}", pipe!(add(10), multiply, divide));
println!("Result is {}", Wrapped(10) >> add >> multiply >> divide);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment