Звичайно, ви можете:
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);
}
Оскільки це Руст, ви повинні взяти до уваги право власності та термін дії закриття .
TL; DR; В основному існує 3 типи закриття (об’єкти, що викликаються):
Fn
: Він не може змінювати об'єкти, які він захоплює.
FnMut
: Він може змінювати об'єкти, які він захоплює.
FnOnce
: Найбільш обмежений. Можна викликати лише один раз, тому що коли він викликаний, він поглинає себе і захоплює.
Див. Коли закриття реалізує Fn, FnMut та FnOnce? для більш детальної інформації
Якщо ви використовуєте простий вказівник на функцію, наприклад, закриття, тоді набір захоплення порожній, і у вас є Fn
смак.
Якщо ви хочете зробити більше вигадливих речей, то вам доведеться використовувати лямбда-функції.
У Rust є відповідні вказівники на функції, які працюють так само, як і в C. Їх тип, наприклад fn(i32) -> i32
. Те Fn(i32) -> i32
, FnMut(i32) -> i32
і FnOnce(i32) -> i32
насправді є рисами. Вказівник на функцію завжди реалізує всі три з них, але у Rust також є замикання, які можуть бути перетворені в покажчики (залежно від того, чи є набір захоплення порожнім) у функції, а можуть і не, але вони реалізують деякі з цих рис.
Так, наприклад, приклад зверху можна розширити:
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;
fun_test_impl(5, times2);
fun_test_impl(5, |x| 2*x);
fun_test_impl(5, |x| y*x);
fun_test_dyn(5, ×2);
fun_test_dyn(5, &|x| 2*x);
fun_test_dyn(5, &|x| y*x);
fun_test_ptr(5, times2);
fun_test_ptr(5, |x| 2*x);
fun_test_ptr(5, |x| y*x);
}