errore ruggine "Non è possibile determinare un tipo per questa espressione"
-
12-12-2019 - |
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?
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.