Fácil Rust

Propagando erro de parse

Enunciado

Escreva uma função soma_strings que recebe duas strings, converte cada uma para i32 e retorna a soma. Use o operador ? para propagar erros de conversão. O retorno deve ser Result<i32, std::num::ParseIntError>.

Requisitos

  • A função deve ter assinatura fn soma_strings(a: &str, b: &str) -> Result<i32, ParseIntError>.
  • Deve usar ? para converter as strings.
  • Em caso de sucesso, retorna Ok(soma).

Código inicial

use std::num::ParseIntError;

fn soma_strings(a: &str, b: &str) -> Result<i32, ParseIntError> {
    // TODO: use ? para converter a e b, depois retorne Ok(soma)
}

fn main() {
    println!("{:?}", soma_strings("10", "20"));
    println!("{:?}", soma_strings("10", "x"));
}

Saída esperada

Ok(30)
Err(ParseIntError { kind: InvalidDigit })
Ver dica

Use let a: i32 = a.parse()?; e depois some. O ? já retorna o erro se a conversão falhar.

Mostrar solução
use std::num::ParseIntError;

fn soma_strings(a: &str, b: &str) -> Result<i32, ParseIntError> {
    let a: i32 = a.parse()?; // se falhar, retorna Err(ParseIntError)
    let b: i32 = b.parse()?; // idem
    Ok(a + b) // sucesso
}

fn main() {
    println!("{:?}", soma_strings("10", "20"));
    println!("{:?}", soma_strings("10", "x"));
}

Passo a passo

  1. A função recebe duas &str e declara retorno Result<i32, ParseIntError>.
  2. a.parse()? tenta converter a para i32. Se der certo, o valor é extraído; se der erro, o Err é retornado imediatamente da função.
  3. O mesmo ocorre com b.
  4. Se ambos forem convertidos, a soma é calculada e envolvida em Ok.
  5. No main, imprimimos os resultados com {:?} para ver as variantes.

Por que funciona

O operador ? é açúcar sintático para um match: se o Result for Ok(v), ele avalia para v; se for Err(e), ele faz return Err(e) (com conversão via From se necessário). Como o tipo de erro da função é ParseIntError, não é necessária conversão.

Erros comuns

  • Esquecer de anotar o tipo: let a = a.parse()?; não compila porque o compilador não sabe para qual tipo converter. Solução: let a: i32 = a.parse()?;.
  • Usar ? em main sem retorno Result: fn main() { let x = "1".parse::<i32>()?; } gera erro porque main retorna (). Corrija fazendo fn main() -> Result<(), ParseIntError> ou tratando o erro.

Outra forma de resolver

Sem ?, usando match:

fn soma_strings(a: &str, b: &str) -> Result<i32, ParseIntError> {
    let a = match a.parse::<i32>() {
        Ok(v) => v,
        Err(e) => return Err(e),
    };
    // ...
}

Mais verboso; o ? é preferível.

Saída esperada

Ok(30)
Err(ParseIntError { kind: InvalidDigit })