What is the correct syntax to return a function in Rust?

Viewed 3392

What is the correct syntax to return a function in Rust?

The following code does not compile, thanks.

  fn identity<T>(a: T) -> T {
    return a;
  };

  fn right<T>(a: T) -> Fn {
    return identity;
  };
3 Answers

Here (playground) is a minimal example:

fn identity<T>(a: T) -> T {
    return a;
}

fn right<T>(_a: T) -> impl Fn(T) -> T {
    return identity;
}

fn main() {
    println!("{}", right(0)(42))
}

You need to:

  • Specify the input argument and output types within the signature, i.e. Fn(T) -> T.
  • Specify that right's return type implements the trait Fn(T) -> T.

Alternatively, you could also have written the function pointer fn(T) -> T as the return type. Since this is not a trait, you would not need the impl keyword:

fn right<T>(_a: T) -> fn(T) -> T {
    return identity;
}

Only fn items and non-capturing closures can be coerced to function pointers, so, while simpler, this will not work in all cases.

This is the best I came up with:

fn identity<T>(a: T) -> T {
    return a;
}

fn right<T>() -> &'static dyn Fn(T)->T {
    return &identity::<T>;
}

fn main() {
    println!("{}", right()(3.1415));
}

playground <-- test it by yourself.

Explanation

&'static dyn Fn(T)->T means that it returns a reference to some object that satisfy the Fn(T)->T trait (because yes Fn(T)->T is indeed a trait, not a type).

Self answer after two answers from others:

I came up with this:

  fn identity<T>(a: T) -> T {
    a
  };

  fn right<T, U>(_a: T) -> fn(U) -> U {
    identity
  };

The return type of right does not have to be identical to input of T of identity.

Related