2015-01-08 18 views
13

Kiedyś miałem coś takiego:Jak przechowywać zamknięcie w Rust?

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

Teraz składnia zamknięcia jest nieaktualne. Mogę zrobić coś takiego:

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

Ale co to za typ Foo obiektu tworzę?

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

mogę również użyć odwołania:

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

Ale myślę, że to wolniej, ponieważ a) deref wskaźnik, oraz b) Teraz nie ma żadnego specjalizacja dla typu FnMut że faktycznie kończy się używany.

Odpowiedz

17

To jest złe: The bezpośredni równoważne byłoby Box<FnMut(uint) -> uint>. Jest to faktycznie to, co faktycznie oznaczała stara składnia.

Korekta: Jak zauważył dbaupp, to nie jest poprawne. Zamknięcia w starym stylu, które używały składni || były odniesieniami do zamknięć przechowywanych na stosie, co czyni je równoważnymi z &'a mut FnMut(uint) -> uint. Zostały one przydzielone sterty i były równoważne Box<FnOnce(uint) -> uint> (można tylko raz wywołać proc). Przepraszam za błąd.

Jeśli chodzi o typ, którego użyjesz w trzecim fragmencie kodu, numer nie jest taki, jak; rodzaje zamknięć są anonimowe i nie można ich bezpośrednio nazwać. Zamiast tego, można by napisać:

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

Jeśli piszesz kod w kontekście, w którym potrzeba aby określić, że chcesz Foo, można napisać:

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

_ mówi systemowi typowemu, aby określił rzeczywisty typ rodzajowy dla ciebie.

Ogólną zasadą, aby który w użyciu, w porządku malejącym:

  • Parametry ogólne: struct Foo<F: FnMut(uint) -> uint>. Jest to najbardziej wydajne, ale oznacza, że ​​konkretna instancja Foo może przechowywać tylko jedno zamknięcie, ponieważ każde zamknięcie ma inny typ betonu.
  • Referencje cechy: &'a mut FnMut(uint) -> uint. Istnieje wskaźnik kierunku, ale teraz możesz zapisać odniesienie do każdego zamknięcia, które ma zgodny podpis wywołania.
  • Zamknięcia zapakowane w pudełka: Box<FnMut(uint) -> uint>. Obejmuje to przydzielanie zamknięcia na stercie, ale nie musisz martwić się o czasy życia. Podobnie jak w przypadku odniesienia, możesz przechowywać każde zamknięcie z kompatybilnym podpisem.
+1

"Bezpośrednim odpowiednikiem będzie Box uint>. Tak naprawdę jest to, co właściwie oznaczała stara składnia." Nie, bezpośrednim odpowiednikiem jest 'i mut FnMut (uint) -> uint'.Tylko 'proc's miał przydzielenie (stary' proc' jest równoważny 'Box ...>'). – huon

+0

(Zwróć także uwagę, że '& FnMut' i' Box huon

+0

@dbaupp: Dzięki. Obwiniam grypę i źle dobrane imię. : P –