25

I've been playing around with Rust the past week. I can't seem to figure out how to pass a function that is defined as a parameter when calling the method, and haven't come across any documentation that shows them being used in that fashion.

Is it possible to define a function in the parameter list when calling a function in Rust?

This is what I've tried so far...

fn main() {

    // This works
    thing_to_do(able_to_pass);

    // Does not work
    thing_to_do(fn() {
        println!("found fn in indent position");
    });

    // Not the same type
    thing_to_do(|| {
        println!("mismatched types: expected `fn()` but found `||`")
    });
}

fn thing_to_do(execute: fn()) {
    execute();
}

fn able_to_pass() {
    println!("Hey, I worked!");
}
ideasman42
  • 42,413
  • 44
  • 197
  • 320
nathansizemore
  • 3,028
  • 7
  • 39
  • 63
  • 1
    Note: you could do `fn named() { .... } thing_to_do(named);` => Rust lets you declare functions in local scopes. – Matthieu M. Aug 07 '14 at 14:06

1 Answers1

19

In Rust 1.0, the syntax for closure parameters is as follows:

fn main() {
    thing_to_do(able_to_pass);

    thing_to_do(|| {
        println!("works!");
    });
}

fn thing_to_do<F: FnOnce()>(func: F) {
    func();
}

fn able_to_pass() {
    println!("works!");
}

We define a generic type constrained to one of the closure traits: FnOnce, FnMut, or Fn.

Like elsewhere in Rust, you can use a where clause instead:

fn thing_to_do<F>(func: F) 
    where F: FnOnce(),
{
    func();
}

You may also want to take a trait object instead:

fn main() {
    thing_to_do(&able_to_pass);

    thing_to_do(&|| {
        println!("works!");
    });
}

fn thing_to_do(func: &Fn()) {
    func();
}

fn able_to_pass() {
    println!("works!");
}
Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
A.B.
  • 15,364
  • 3
  • 61
  • 64
  • 4
    Why ? Because functions have no environment while closures have, thus it's trivial to convert a function to a closure (add a null environment) while the reverse is much more complicated (requires a trampoline I think). – Matthieu M. Aug 07 '14 at 14:05
  • The `thing_to_do` takes ownership over `func`, meaning `func` cannot be reused in the caller. I've done some work to make it reusable using `&` but, I still haven't got how to make the `apply` function generic over any type and across the `FnOnce, Fn, FnMut` variations. – CMCDragonkai Mar 29 '16 at 14:23