erro de ferrugem “não é possível determinar um tipo para esta expressão”
-
12-12-2019 - |
Pergunta
eu escrevo um programa simples de ferrugem.
fn main(){
let port = 80;
result::chain(connect("localhost", port as u16)) {|s|
send(s,str::bytes("hello world"));
};
há algum erro nisso.
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
o que aconteceu nele?
Solução
O compilador não conseguiu inferir o tipo que esta invocação de result::chain
deveria retornar.É difícil ter certeza sem conhecer os tipos de connect
e send
, mas eu acho que é porque o corpo do seu bloco lambda está (provavelmente por engano) resultando no tipo nil.
O tipo de cada bloco em ferrugem é determinado por sua 'expressão final', e as expressões finais são criadas deixando o ponto-e-vírgula fora da instrução final.Presumivelmente, send
retorna o result
digite e é por isso que você está usando result::chain
nele - de modo que o resultado de toda a expressão seja o resultado de send
.Para fazer isso funcionar o send
expressão não deve ser terminada por ponto e vírgula.Então seu bloco lambda retornará o resultado de send
.
Algo assim pode funcionar melhor:
fn main(){
let port = 80;
result::chain(connect("localhost", port as u16)) {|s|
send(s,str::bytes("hello world")) // <- no semicolon
};
}
Quando a inferência de tipos falha, às vezes pode ser útil dividir as expressões em séries menores de instruções e inserir tipos explícitos até descobrir onde os tipos não estão correspondendo corretamente.Se eu acertasse algo assim e não conseguisse descobrir olhando por um tempo, então eu começaria a reescrevê-lo como
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);
}
Claro, substituindo quaisquer tipos connect
e send
realmente usar.Em algum ponto do processo de desmontar tudo, você descobrirá onde você e o compilador discordam.