Pass variable into a scope in rust

Viewed 128

I have a problem trying to implement a callback to filter method in Rust. I have this function:

fn filter_by_mod(num: i32) -> fn(x: &i32) -> bool {
    let func = |x: &i32| {
        x.to_owned() % num == 0
    };
    return func;
}

I am trying to filter by mod and I would like to pass the number by paramenter and use in the func clousure, but when I try to compile I have the following error:

fn filter_by_mod(num: i32) -> fn(x: &i32) -> bool {
   |                                 ------------------- expected `for<'r> fn(&'r i32) -> bool` because of return type
9  |       let func = |x: &i32| {
   |  ________________-
10 | |         x.to_owned() % num == 0
11 | |     };
   | |_____- the found closure
12 |       return func;
   |              ^^^^ expected fn pointer, found closure
   |
   = note: expected fn pointer `for<'r> fn(&'r i32) -> bool`
                 found closure `[closure@.\main.rs:9:16: 11:6]`
note: closures can only be coerced to `fn` types if they do not capture any variables
  --> .\main.rs:10:24
   |
10 |         x.to_owned() % num == 0
   |                        ^^^ `num` captured here

error: aborting due to previous error

How I can pass the number to func scope? I hope that you can understandme, because my english is not good. Thanks.

2 Answers

There are 2 problems why the example does not compile:

  • You are returning fn type. In rust it is a function pointer, but a closure is not a function, so you need to return an implementation of Fn trait.
  • But default closure borrows the context parameters, so you need to move it:
fn filter_by_mod(num: i32) -> impl Fn(&i32) -> bool {
    let func = move |x: &i32| {
        x.to_owned() % num == 0
    };
    return func;
}

Two things happening here:

  • You need to move num into the new function
  • Your function signature is wrong, you cannot return a function pointer, you need to use impl + function trait signature needed.

With minor stylish adjustments too:

fn filter_by_mod(num: i32) -> impl Fn(&i32) -> bool {
    move |x: &i32| {
        x.to_owned() % num == 0
    }
}

Playground

Related