snippetrustCritical
How do you pass a Rust function as a parameter?
Viewed 0 times
youhowfunctionparameterrustpass
Problem
Can I pass a function as a parameter? If not, what is a good alternative?
I tried some different syntaxes but I have not found the right one. I know I can do this:
but that's not passing the function as a parameter to another function:
I tried some different syntaxes but I have not found the right one. I know I can do this:
fn example() {
let fun: fn(value: i32) -> i32;
fun = fun_test;
fun(5i32);
}
fn fun_test(value: i32) -> i32 {
println!("{}", value);
value
}but that's not passing the function as a parameter to another function:
fn fun_test(value: i32, (some_function_prototype)) -> i32 {
println!("{}", value);
value
}Solution
Sure you can:
As this is Rust, you have to take into account the ownership and lifetime of the closure.
TL;DR; Basically there are 3 types of closures (callable objects):
See When does a closure implement Fn, FnMut and FnOnce? for more details
If you are using a simple pointer-to-function like closure, then the capture set is empty and you have the
If you want to do more fancy stuff, then you will have to use lambda functions.
In Rust there are proper pointers to functions, that work just like those in C. Their type is for example
So for example, the example from above can be expanded:
fn fun_test(value: i32, f: &dyn Fn(i32) -> i32) -> i32 {
println!("{}", f(value));
value
}
fn times2(value: i32) -> i32 {
2 * value
}
fn main() {
fun_test(5, ×2);
}As this is Rust, you have to take into account the ownership and lifetime of the closure.
TL;DR; Basically there are 3 types of closures (callable objects):
Fn: It cannot modify the objects it captures.
FnMut: It can modify the objects it captures.
FnOnce: The most restricted. Can only be called once because when it is called it consumes itself and its captures.
See When does a closure implement Fn, FnMut and FnOnce? for more details
If you are using a simple pointer-to-function like closure, then the capture set is empty and you have the
Fn flavor.If you want to do more fancy stuff, then you will have to use lambda functions.
In Rust there are proper pointers to functions, that work just like those in C. Their type is for example
fn(i32) -> i32. The Fn(i32) -> i32, FnMut(i32) -> i32 and FnOnce(i32) -> i32 are actually traits. A pointer to a function always implements all three of these, but Rust also has closures, that may or may not be converted to pointers (depending on whether the capture set is empty) to functions but they do implement some of these traits.So for example, the example from above can be expanded:
fn fun_test_impl(value: i32, f: impl Fn(i32) -> i32) -> i32 {
println!("{}", f(value));
value
}
fn fun_test_dyn(value: i32, f: &dyn Fn(i32) -> i32) -> i32 {
println!("{}", f(value));
value
}
fn fun_test_ptr(value: i32, f: fn(i32) -> i32) -> i32 {
println!("{}", f(value));
value
}
fn times2(value: i32) -> i32 {
2 * value
}
fn main() {
let y = 2;
//static dispatch
fun_test_impl(5, times2);
fun_test_impl(5, |x| 2*x);
fun_test_impl(5, |x| y*x);
//dynamic dispatch
fun_test_dyn(5, ×2);
fun_test_dyn(5, &|x| 2*x);
fun_test_dyn(5, &|x| y*x);
//C-like pointer to function
fun_test_ptr(5, times2);
fun_test_ptr(5, |x| 2*x); //ok: empty capture set
fun_test_ptr(5, |x| y*x); //error: expected fn pointer, found closure
}Code Snippets
fn fun_test(value: i32, f: &dyn Fn(i32) -> i32) -> i32 {
println!("{}", f(value));
value
}
fn times2(value: i32) -> i32 {
2 * value
}
fn main() {
fun_test(5, ×2);
}fn fun_test_impl(value: i32, f: impl Fn(i32) -> i32) -> i32 {
println!("{}", f(value));
value
}
fn fun_test_dyn(value: i32, f: &dyn Fn(i32) -> i32) -> i32 {
println!("{}", f(value));
value
}
fn fun_test_ptr(value: i32, f: fn(i32) -> i32) -> i32 {
println!("{}", f(value));
value
}
fn times2(value: i32) -> i32 {
2 * value
}
fn main() {
let y = 2;
//static dispatch
fun_test_impl(5, times2);
fun_test_impl(5, |x| 2*x);
fun_test_impl(5, |x| y*x);
//dynamic dispatch
fun_test_dyn(5, ×2);
fun_test_dyn(5, &|x| 2*x);
fun_test_dyn(5, &|x| y*x);
//C-like pointer to function
fun_test_ptr(5, times2);
fun_test_ptr(5, |x| 2*x); //ok: empty capture set
fun_test_ptr(5, |x| y*x); //error: expected fn pointer, found closure
}Context
Stack Overflow Q#36390665, score: 258
Revisions (0)
No revisions yet.