K
dsdadasda schrieb:
danke jedenfalls dass du mich darauf aufmerksam gemacht hast, dass es diese sprache überhaupt gibt. werd ich mir bei zeiten einmal näher ansehen!
Gerne!
Was ich noch nicht erwähnt hatte: Es gibt auch Funktionszeiger und Closures. Allerdings sind Closures noch immer "boxed". Das entspricht in C++ einer Kombination aus std::function und [&] ... bzw [dings=move(dings)] ... je nachdem, welche Closure ihr benutzt.
Es gibt Referenzclosures (wie z.B. |x|{2*x+b} ), die sich mit einer Referenz auf die lokale Umgebung (im Beispiel für das b ) beziehen aber dementsprechend keine besonders große Lebenszeit haben können. Es reicht, um Funktionen damit zu füttern, die so etwas nicht wo anders speichern wollen:
fn main() {
let b = 1;
for x in range(0i,10).map(|z|{2*z+b}) {
print!(" {}",x);
}
println!("");
}
Und es gibt noch "One-Shot Closures", die einige Variablen aus ihrer Umgebung implizit per move "klauen". Die schreibt man mit proc . Diese können dann auch irgendwo gespeichert oder an einen anderen Task übergeben und dort einmal ausgeführt werden:
fn main() {
let (tx,rx) = channel(); // Unidirektionaler Kanal mit Sende- (tx)
// und Empfangseinheit (rx)
spawn( proc(){ // <-- so eine "one-shot closure"
tx.send("Hello World!"); // tx hat sie sich aus main geklaut
});
let msg = rx.recv(); // blockiert bis die Nachricht da ist
println!("{}",msg);
}
Man sieht hier auch, dass ich nirgens einen Typ hingeschrieben habe. Das ist die Typinferenz à la Hindley-Milner in Aktion. Der Kanal ist schon typisiert. Ich kann da jetzt nicht einmal einen int und dann einen string rüberschicken. Das coole dabei ist, dass relativ viel (wie u.a. auch Kanäle) selbst in Rust in der Standardbibliothek implementiert sind, also nicht alles Compiler-Magie ist. Man kann übrigens die "Sendeeinheit" (tx) auch klonen, so dass mehrere Tasks etwas in den Kanal stecken können.
Bzgl "boxed closure": Das soll noch wegfallen. Die Rust-Macher wollen auch "unboxed closures" zulassen, die sich dann schön inlinen lassen, so, wie man das von C++11 Lambdas auch kennt. Das dürfte dann nochmal ein Performancegewinn sein.
Der ganze Iterator-Kram aus der Standardbibliothek arbeitet aber ohne runtime Dispatch (wie in C++ auch). Die Typen sind zur Compilezeit ja alle klar. So ein for x in iterator -Loop kann deswegen gut optimiert werden.