2015-03-31 15 views
6

Ho cercato di creare vettore di chiusure in questo modo:Qual è il tipo dedotto di un vettore di chiusure?

fn main() { 
    let mut vec = Vec::new(); 

    vec.push(Box::new(||{ 10 })); 
    vec.push(Box::new(||{ 20 })); 

    println!("{}", vec[0]()); 
    println!("{}", vec[1]()); 
} 

che ha dato il seguente rapporto di errore:

error: mismatched types: 
expected `[closure RustTest.rs:4:20: 4:28]`, 
    found `[closure RustTest.rs:5:20: 5:28]` 
(expected closure, 
    found a different closure) [E0308] 
RustTest.rs:5 vec.push(Box::new(||{ 20 })); 
            ^~~~~~~~ 

ho riparato specificando il tipo in modo esplicito:

let mut vec: Vec<Box<Fn() -> i32>> = Vec::new(); 

Così la mia domanda è: qual è il tipo dedotto di vec e perché è così?

risposta

4

Ogni chiusura ha un tipo anonimo, generato automaticamente, univoco. Non appena aggiungi la prima chiusura al vettore, questo è il tipo di tutti gli elementi nel vettore. Tuttavia, quando si tenta di aggiungere la seconda chiusura, ha un diverso tipo autogenerato, univoco e anonimo, quindi viene visualizzato l'errore.

Le chiusure sono essenzialmente struct s create dal compilatore che implementa uno dei tratti Fn*. Lo struct contiene i campi per tutte le variabili acquisite dalla chiusura, quindi per definizione deve essere univoco, poiché ogni chiusura acquisirà numeri e tipi di variabili diversi.

Perché non può semplicemente dedurre Box<Fn() -> i32>?

"impossibile" è una domanda difficile a cui rispondere. È possibile che il compilatore possa scorrere tutti i tratti di ogni tipo che viene usato per vedere se qualche intersezione ha causato la compilazione del codice, ma per me è un po 'magico. Potresti provare ad aprire una richiesta di funzione o discuterla su uno dei forum per vedere se c'è un'accettazione generale di tale idea.

Tuttavia, Rust tenta di rendere le cose esplicite, in particolare le cose che potrebbero comportare prestazioni. Quando passi da una struttura concreta a un oggetto tratto, stai introducendo l'indirezione, che ha la possibilità di essere più lento.

In questo momento, i tratti Fn* funzionano allo stesso modo come un tratto user-costruito:

trait MyTrait { 
    fn hello(&self) {} 
} 

struct MyStruct1; 
impl MyTrait for MyStruct1 {} 

struct MyStruct2; 
impl MyTrait for MyStruct2 {} 

fn main() { 
    let mut things = vec![]; 
    things.push(MyStruct1); 
    things.push(MyStruct2); 
} 
+0

Perché non può solo dedurre Box i32>? – VRW

+0

Si scopre che ogni funzione ha il suo tipo distinto http://stackoverflow.com/a/28151275/4734315 Sono curioso di sapere quale sia stata la ragione di tale decisione. – VRW

+0

@VRW è quello che intendevo con la mia prima frase: "Ogni chiusura ha un tipo anonimo generato automaticamente, unico." Hai un suggerimento su come avrei potuto formularlo meglio? – Shepmaster

Problemi correlati