Domanda

Scrivo un semplice programma di ruggine.

fn main(){
    let port = 80;
    result::chain(connect("localhost", port as u16)) {|s|
    send(s,str::bytes("hello world"));
};
.

C'è qualche errore su di esso.

macmatoMacBook-Air-2:rust-http kula$ rustc http.rs
http.rs:40:4: 40:52 error: cannot determine a type for this expression
http.rs:40     result::chain(connect("localhost", port as u16)) {|s|
           ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
error: aborting due to previous errors
.

Cosa è successo su di esso?

È stato utile?

Soluzione

Il compilatore non è riuscito a dedurre il tipo che questa invocazione di result::chain deve tornare. È difficile raccontare sicuramente senza conoscere i tipi di connect e send, ma immagino che sia perché il corpo del tuo blocco di lambda è (probabilmente erroneamente) con conseguente tipo di tipo.

Il tipo di ogni blocco in ruggine è determinato dalla sua "espressione di coda", e le espressioni della coda vengono create lasciando il punto e virgola della dichiarazione finale. Presumibilmente, send restituisce il tipo result ed è per questo che si utilizza result::chain su di esso - in modo che il risultato dell'intera espressione sia il risultato di send. Per rendere questo lavoro l'espressione send non deve essere terminata da un punto e virgola. Quindi il blocco Lambda restituirà il risultato di send.

Qualcosa come questo può funzionare meglio:

fn main(){
    let port = 80;
    result::chain(connect("localhost", port as u16)) {|s|
        send(s,str::bytes("hello world")) // <- no semicolon
    };
}
.

Quando il tipo di inferenza fallisce può a volte può essere utile alle espressioni di rottura in serie di istruzioni più piccole e inserire tipi espliciti finché non si capisce dove non si corrispondono correttamente. Se colpisco qualcosa del genere e non riuscirò a capirlo con lo occhi per un po ', allora avrei cominciato a riscriverlo come

fn main(){
    let port = 80;
    let conn_result: result::t<connection, str> = connect("localhost", port as u16);
    let send_fn =  fn@(s: connection) -> result::t<str, str> {
        let send_result: result<str, str> = send(s,str::bytes("hello world"));
        ret send_result;
    };
    let res: result<str, str> = result::chain(conn_result, send_fn);
}
.

Ovviamente sostituire qualsiasi tipo di generazione di connect e send effettivamente uso. Ad un certo punto del processo di tirare tutto a parte, scoprirai dove tu e il compilatore non sono d'accordo.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top