Oczywiście że możesz:
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);
}
Ponieważ jest to Rust, musisz wziąć pod uwagę własność i czas życia zamknięcia .
TL; DR; Zasadniczo istnieją 3 typy domknięć (obiekty wywoływalne):
Fn
: Nie może modyfikować przechwyconych obiektów.
FnMut
: Może modyfikować przechwycone obiekty.
FnOnce
: Najbardziej ograniczone. Można go wywołać tylko raz, ponieważ gdy jest wywoływany, konsumuje siebie i łapie.
Zobacz Kiedy zamknięcie implementuje Fn, FnMut i FnOnce? po więcej szczegółów
Jeśli używasz prostego wskaźnika do funkcji, takiego jak zamknięcie, zbiór przechwytywania jest pusty i masz Fn
smak.
Jeśli chcesz robić bardziej wymyślne rzeczy, będziesz musiał użyć funkcji lambda.
W Rust znajdują się odpowiednie wskaźniki do funkcji, które działają tak samo jak w C. Ich typ to na przykład fn(i32) -> i32
. Pliki Fn(i32) -> i32
, FnMut(i32) -> i32
iFnOnce(i32) -> i32
są w rzeczywistości cechy. Wskaźnik do funkcji zawsze implementuje wszystkie trzy z nich, ale Rust ma również domknięcia, które mogą, ale nie muszą, być konwertowane na wskaźniki (w zależności od tego, czy zbiór przechwytywania jest pusty) do funkcji, ale implementują one niektóre z tych cech.
Na przykład przykład z góry można rozwinąć:
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);
}