Estou lendo o exemplo do canvas hello world na documentação do wasm-bindgen e estou confuso sobre esta parte do código:
#[wasm_bindgen(start)]
fn start() {
let document = web_sys::window().unwrap().document().unwrap();
let canvas = document.get_element_by_id("canvas").unwrap();
let canvas: web_sys::HtmlCanvasElement = canvas
.dyn_into::<web_sys::HtmlCanvasElement>()
.map_err(|_| ()) // What does this do?
.unwrap();
// ...
}
Olhando para a definição da função para map_err
, vejo:
impl<T, E> Result<T, E> {
pub fn map_err<F, O: FnOnce(E) -> F>(self, op: O) -> Result<T, F> {
match self {
Ok(t) => Ok(t),
Err(e) => Err(op(e)),
}
}
}
Então, se entendi corretamente, map_error
pega um Result<T,E>
e um fechamento que pega E e retorna F. Se o resultado for Ok, ele retorna T inalterado. Se for Err, ele aplica o fechamento e retorna o resultado.
O exemplo no canvas "olá mundo", no entanto, parece inútil. Parece que o dyn_into
retornará um Result<HtmlCanvasElement,Element>
, e então map_err
o transformará em um Result<HtmlCanvasElement,()>
se o resultado for Err. No entanto, a próxima linha é .unwrap()
, então se o resultado for Err, ele entrará em pânico antes de chegar ao final da instrução. Se o resultado for Ok, o map_err
não alterará o valor do resultado.
Sou relativamente novo em Rust e estou tentando entender o que a map_err
linha está realizando aqui. Como o Result é desembrulhado na linha seguinte, parece que você poderia remover toda a linha de código e nada mudaria. Isso é apenas um erro ou este código está fazendo algo que não é óbvio para mim?
O
Err
lado deResult
geralmente contém um valor que representa um erro, mas em alguns casos (como este) em que o valor original é consumido pela operação, se a operação falhar, oErr
lado pode ser usado para retornar o valor original caso você queira tentar algo diferente com ele.Sua avaliação do que
map_err
está sendo feito aqui está correta: está descartando oElement
daErr
variante e substituindo-o por()
.Observe que a mensagem de pânico
Result::unwrap
produzida nesseErr
caso incluirá o valor formatado para depuração contido naErr
variante. Ao mapear o erro para()
, isso evita o descarte da formatação de depuração doElement
, o que pode não ser muito útil. Se nada mais no programa formatar um debug,Element
isso também pode permitir que o otimizador remova a implementaçãoElement
deDebug
, o que reduziria o tamanho do programa compilado.Você também pode ver esse padrão em casos em que o valor armazenado na
Err
variante não é implementadoDebug
e, portanto,unwrap
não pode ser chamado até ser substituído por algo que seja. (Embora geralmente.ok().unwrap()
seja mais sucinto..ok()
converteResult<T, E>
paraOption<T>
, descartando o valor de erro e, em seguida,.unwrap()
invocaOption
'sunwrap
em vez deResult
's.)