Sicher kannst du:
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);
}
Da dies Rust ist, müssen Sie das Eigentum und die Lebensdauer der Schließung berücksichtigen .
TL; DR; Grundsätzlich gibt es 3 Arten von Verschlüssen (aufrufbare Objekte):
Fn: Die erfassten Objekte können nicht geändert werden.
FnMut: Es kann die erfassten Objekte ändern.
FnOnce: Am meisten eingeschränkt. Kann nur einmal aufgerufen werden, da es sich selbst und seine Erfassungen verbraucht, wenn es aufgerufen wird.
Siehe Wann implementiert ein Abschluss Fn, FnMut und FnOnce? für mehr Details
Wenn Sie einen einfachen Zeiger auf eine Funktion wie das Schließen verwenden, ist das Erfassungsset leer und Sie haben den FnGeschmack.
Wenn Sie mehr ausgefallene Sachen machen wollen, müssen Sie Lambda-Funktionen verwenden.
In Rust gibt es richtige Zeiger auf Funktionen, die genau wie in C funktionieren. Ihr Typ ist zum Beispiel fn(i32) -> i32. Die Fn(i32) -> i32, FnMut(i32) -> i32und FnOnce(i32) -> i32sind tatsächlich Züge. Ein Zeiger auf eine Funktion implementiert immer alle drei, aber Rust hat auch Verschlüsse, die in Zeiger (abhängig davon, ob der Erfassungssatz leer ist) auf Funktionen konvertiert werden können oder nicht, aber einige dieser Merkmale implementieren.
So kann beispielsweise das Beispiel von oben erweitert werden:
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);
}