2015-01-08 7 views
13

Ich habe etwas zu haben, wie:Wie lagere ich eine Schließung in Rust?

struct Foo { 
    pub foo: |uint| -> uint, 
} 

Nun ist die Schließung Syntax ist veraltet. Ich kann so etwas wie tun:

struct Foo<F: FnMut(uint) -> uint> { 
    pub foo: F, 
} 

Aber was ist dann der Typ eines Foo Objekt ich erstellen?

let foo: Foo<???> = Foo { foo: |x| x + 1 }; 

ich auch eine Referenz verwenden:

struct Foo<'a> { 
    pub foo: &'a mut FnMut(uint) -> uint 
} 

Aber ich denke, es ist langsamer, weil a) der Zeiger deref, und b) jetzt für die Art von FnMut gibt es keine Spezialisierung, die endet als tatsächlich benutzt.

Antwort

17

Das ist falsch: Die direkte Äquivalent Box<FnMut(uint) -> uint> wäre. Dies ist tatsächlich, was die alte Syntax tatsächlich bedeutete.

Korrektur: Wie dbaupp darauf hingewiesen hat, stimmt das nicht. Verschlüsse alten Stils, die die || Syntax verwendeten, waren Verweise auf Verschlüsse, die auf dem Stapel gespeichert waren, was sie zu &'a mut FnMut(uint) -> uint äquivalent machte. Es war proc s, die heap-allokiert wurden, und waren Box<FnOnce(uint) -> uint> (Sie können nur einmal eine proc aufrufen). Ich entschuldige mich für den Fehler.

Für welchen Typ Sie in Ihrem dritten Code-Snippet verwenden würden, ist nicht eins; Verschlusstypen sind anonym und können nicht direkt benannt werden. Stattdessen würden Sie schreiben:

let foo = Foo { foo: |x| x + 1 }; 

Wenn Sie Code in einem Kontext gerade schreiben, wo Sie Notwendigkeit angeben, dass Sie eine Foo wollen, würden Sie schreiben:

let foo: Foo<_> = Foo { foo: |x| x + 1 }; 

Die _ weist das Typsystem an, den tatsächlichen generischen Typ für Sie abzuleiten.

Die Faustregel zu die, in absteigender Reihenfolge zu verwenden:

  • Allgemeine Parameter: struct Foo<F: FnMut(uint) -> uint>. Dies ist der effizienteste, aber es bedeutet, dass eine spezifische Foo Instanz nur einen Verschluss speichern kann, da jeder Verschluss einen anderen konkreten Typ hat.
  • Merkmalsreferenzen: &'a mut FnMut(uint) -> uint. Es gibt eine Zeigerindirektion, aber jetzt können Sie einen Verweis auf alle Schließungen speichern, die eine kompatible Rufunterschrift haben.
  • Verpackte Verschlüsse: Box<FnMut(uint) -> uint>. Dies beinhaltet die Zuweisung der Schließung auf dem Heap, aber Sie müssen sich keine Sorgen über die Lebensdauer machen. Wie bei einer Referenz können Sie jede Schließung mit einer kompatiblen Signatur speichern.
+1

"Das direkte Äquivalent wäre Box Uint>. Dies ist effektiv, was die alte Syntax eigentlich bedeutete." Nein, das direkte Äquivalent ist "& mut FnMut (uint) -> uint".Nur 'proc's hatten eine Zuweisung (das alte' proc' ist äquivalent zu 'Box ...>'). – huon

+0

(Beachten Sie auch, dass '& FnMut' und' Box huon

+0

@dbaupp: Danke. Ich beschuldige die Grippe und den schlecht gewählten Namen. : P –

Verwandte Themen