Higher order functions in Rust?

#1
  1. This is what I have so far:

/*

(defn foo [f]
  (fn [x]
    (+ 1 (f (* x 2))) ) )
*/


pub fn foo(f: Fn(&i32) -> i32) -> (Fn (&i32) -> i32) {
    panic!()
    // ???
}
// This doesn't even compile due to


// error:

/*

33 | pub fn foo(f: Fn(&i32) -> i32) -> (Fn (&i32) -> i32) {
   |                                    ^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
   |
   = help: the trait `std::marker::Sized` is not implemented for `(dyn for<'r> std::ops::Fn(&'r i32) -> i32 + 'static)`
   = note: to learn more, visit <https://doc.rust-lang.org/book/second-edition/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
   = note: the return type of a function must have a statically known size


*/
  1. How do we fix this? (PS: In this particular case, probably easier to learn from working example than ‘hints’). Thanks!
#2
pub fn foo<F: Fn(i32) -> i32>(f: F) -> impl Fn (i32) -> i32 {
    move |x| f(x * 2) + 1
}

Yours didn’t work because Fn is a trait, and dyn Trait is unsized.

2 Likes
#3

Thanks!

Playing with the example a bit:

pub fn foo<F: Fn(i32) -> i32>(f: F) -> impl Fn (i32) -> i32 {
    move |x| f(x * 2) + 1
}


// we can't do this because F is no longer in scope?
pub fn foo2<F: Fn(i32) -> i32>(f: F) -> impl F {
    move |x| f(x * 2) + 1
}


// Why can't do we do this?
type MyFunc = Fn(i32) -> i32;
pub fn foo3<F: MyFunc>(f: F) -> impl F {
    move |x| f(x * 2) + 1
}

Is there anyway to reduce the repetition of specifying the function type signature twice, or are we stuck with it?

#4

the impl Trait syntax in the return type means “I am going to return some type which I don’t want to name, but implements this trait”. So impl F doesn’t make any sense because you can’t implement a type.
As for the second question, we don’t have constraint aliases, so we can’t do any of that. When you say type MyFunc = Fn(i32) -> i32;, you are creating an alias to the dynamically dispatched trait object Fn(i32) -> i32.

impl Trait docs
https://rust-lang-nursery.github.io/edition-guide/rust-2018/trait-system/impl-trait-for-returning-complex-types-with-ease.html

trait object docs
https://doc.rust-lang.org/book/trait-objects.html

https://doc.rust-lang.org/book/ch17-02-trait-objects.html

1 Like