But as always, depends on where you come from. I mostly deal with lisp languages nowadays, so guessing it's just my view that the line quoted above seems complex enough to not be interested one bit in Rust.
But as always, depends on where you come from. I mostly deal with lisp languages nowadays, so guessing it's just my view that the line quoted above seems complex enough to not be interested one bit in Rust.
The equivalent in Haskell would be "compose :: (a -> a) -> (a -> a) -> a -> a", which lacks "impl" because it boxes all closures (each closure in Rust has its own type), and lacks "Fn" because it doesn't care about what kind of access the closure needs to its context (Rust distinguishes between Fn, FnMut and FnOnce). Still, the Rust is only a tiny bit more complicated than the Haskell.
#![feature(trait_alias)]
trait Map<T> = Fn(T) -> T;
fn compose <T>(f1: impl Map<T>, f2: impl Map<T>) -> impl Map<T> {
|n| f1(f2(n))
}template<typename T> using Map = std::function<T (T)>;
fn compose<T>(
f1: impl Fn(T)->T,
f2: impl Fn(T)->T
) -> impl Fn(T)->T
{
// both arguments as well as the returned value
// are functions which take and return the generic type T.
// (to be precise, they implement the Fn trait).
}
let returned_function = compose(|val| val == 1, |val| val < 0);
let value: bool = returned_function(true); fn compose<T, F: Fn(T)->T>(f1: F, f2: F) -> F { fn compose<T, F: Fn(T) -> T, G: Fn(T) -> T>(f: F, g: G) -> impl Fn(T) - > T
or: fn compose<T, F, G>(f: F, g: G) -> impl Fn(T) -> T
where F: Fn(T) -> T, G: Fn(T) -> Thttps://doc.rust-lang.org/nightly/std/iter/trait.Iterator.ht...
... and `impl Trait` exists to be able to have return types which are difficult, verbose, or impossible to name.
compose(|x| x, |x| x)
because the closures have the same type.It's a fun little thing, and a good example of why impl Trait in argument position is a really nice addition to Rust, even though based on what we were originally excited about (impl Trait in return position for returning Iterators and other such things), the argument position form didn't seem so important.
fn compose<T, F: Fn(T) -> T>(f1: F, f2: F) -> F
As far as I'm aware the only way to write a function like that is fn compose<T, F: Fn(T) -> T>(f1: F, f2: F) -> F {
f1
}
and even then you can only call it like this let clos = |x| 2 * x;
compose(clos, clos);Bt then again, maybe it depends on where you come from.