Seguro que puede:
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);
}
Como se trata de Rust, debe tener en cuenta la propiedad y la vida útil del cierre .
TL; DR; Básicamente, existen 3 tipos de cierres (objetos invocables):
Fn
: No puede modificar los objetos que captura.
FnMut
: Puede modificar los objetos que captura.
FnOnce
: El más restringido. Solo se puede llamar una vez porque cuando se llama se consume a sí mismo y sus capturas.
Consulte ¿ Cuándo implementa un cierre Fn, FnMut y FnOnce? para más detalles
Si está utilizando un cierre simple de puntero a función, entonces el conjunto de captura está vacío y tiene el Fn
sabor.
Si quieres hacer cosas más sofisticadas, entonces tendrás que usar funciones lambda.
En Rust hay punteros adecuados para funciones, que funcionan igual que los de C. Su tipo es, por ejemplo fn(i32) -> i32
. El Fn(i32) -> i32
, FnMut(i32) -> i32
y FnOnce(i32) -> i32
en realidad son rasgos. Un puntero a una función siempre implementa los tres, pero Rust también tiene cierres, que pueden o no convertirse en punteros (dependiendo de si el conjunto de captura está vacío) a funciones, pero implementan algunos de estos rasgos.
Entonces, por ejemplo, el ejemplo anterior se puede expandir:
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);
}