Skip to content

Instantly share code, notes, and snippets.

@berkus
Forked from rust-play/playground.rs
Created August 29, 2019 07:34
Show Gist options
  • Save berkus/79408c22e663225f945bcab9dc5381b3 to your computer and use it in GitHub Desktop.
Save berkus/79408c22e663225f945bcab9dc5381b3 to your computer and use it in GitHub Desktop.
Code shared from the Rust Playground
#![feature(unboxed_closures, fn_traits)]
fn main() {
let add = |a: i32, b: i32| a + b;
let sqr = |a: i32| a.pow(2);
let add_two = |a: i32| a + 2;
assert_eq!(chain(add, sqr)(2, 3), 25);
assert_eq!(
chain(
chain(
chain(add_two, sqr),
add_two
),
add_two
)(2), 20);
assert_eq!(chain(sqr, sqr)(2), 16);
}
pub struct Chain<F, G>(F, G);
impl<F, G> Chain<F, G> {
fn new<A, B, C>(f: F, g: G) -> Self where
F: FnOnce<A, Output = B>,
G: FnOnce<(B,), Output = C>,
{
Chain(f, g)
}
}
impl<A, B, C, F, G> FnOnce<A> for Chain<F, G>
where
F: FnOnce<A, Output = B>,
G: FnOnce<(B,), Output = C>,
{
type Output = C;
extern "rust-call" fn call_once(self, args: A) -> Self::Output {
let Chain(f1, f2) = self;
f2.call_once((f1.call_once(args),))
}
}
fn chain<A, B, C, F, G>(f: F, g: G) -> impl FnOnce<A, Output = C>
where
F: FnOnce<A, Output = B>,
G: FnOnce<(B,), Output = C>,
{
Chain::new(f, g)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment