In Rust sind Closures anonyme Funktionen, die Variablen aus dem äußeren Sichtbereich "erfassen" können. Syntax:
let add = |a: i32, b: i32| a + b;
In Rust gibt es drei Arten von Closures (unterscheiden sich in der Art der Variablenübernahme):
&T), kann mehrfach aufgerufen werden, ohne die Umgebung zu verändern.&mut T), kann Daten innerhalb des Closures bei einem Aufruf ändern.T).Rust bestimmt automatisch den benötigten Typ, aber Sie können ihn explizit angeben.
Beispiel für Unterschiede:
let s = String::from("hello"); // FnOnce let consume = move || println!("{}", s); // s ist nach dem Aufruf nicht mehr verfügbar
Warum kann ein Closure mit dem Schlüsselwort move nicht FnOnce sein, sondern als Fn oder FnMut betrachtet werden?
Antwort: Das Schlüsselwort move überträgt die Erfassung von Variablen durch Eigentum, aber wenn die Daten innerhalb des Closures nicht verändert und nicht zerstört werden, bleibt das Closure mit Fn/FnMut kompatibel. Zum Beispiel:
let s = String::from("abc"); let c = move || println!("String: {}", s); // c: impl Fn() c();
c kann mehrfach aufgerufen werden: der Wert s wurde in das Closure kopiert, aber nicht zerstört.
Geschichte
Ein unerfahrener Rust-Entwickler in einem Datenstromprojekt versuchte, ein Closure ohne move zu schreiben, das in einen anderen Thread übergeben wurde. Infolgedessen beschwerte sich der Compiler über outlived borrow, und er musste sich dringend mit den Feinheiten von lifetime und move befassen.
Geschichte
Mutability wurde in das Closure eingeführt, ohne den Typ auf FnMut zu ändern, was an allen Stellen der Verwendung von Iteratoren "mismatched types" verursachte.
Geschichte
Bei der Verarbeitung eines großen Arrays übernahm das Closure durch move die gesamte Sammlung, ohne es zu merken, und verschob damit das Eigentum, sodass der externe Code nach der ersten Iteration den Zugriff auf die Daten verlor, was zu Versuchen führte, auf den moved value zuzugreifen.