O Operador de Interrogação '?'
Parte da seção Lógica & Fluxo do Journey de Rust da Coddy. Lição 46 de 66.
Ao trabalhar com funções que retornam Result, muitas vezes você precisa lidar com erros tratando-os localmente ou repassando-os para a função chamadora. Rust fornece um operador elegante para esse padrão comum: o operador de ponto de interrogação ?.
O operador ? fornece uma maneira simples de propagar erros sem escrever instruções match detalhadas. Quando você coloca ? após um Result, ele desempacota automaticamente um valor Ok ou retorna imediatamente da função atual com o Err:
fn parse_and_double(s: &str) -> Result<i32, std::num::ParseIntError> {
let number = s.parse::<i32>()?; // Se a análise falhar, retorne o erro
Ok(number * 2) // Se for bem-sucedido, dobre o número
}Isso equivale a escrever uma instrução match completa, mas de forma muito mais concisa. Se s.parse::<i32>() retornar um Ok, o ? extrai o valor e o atribui a number. Se retornar um Err, o ? retorna imediatamente esse erro de toda a função.
Observe a sintaxe ::<i32>. Isso é chamado de turbofish e informa ao Rust em qual tipo a string deve ser analisada. A função retorna Result<i32, std::num::ParseIntError>, em que i32 é o tipo de sucesso e std::num::ParseIntError é o tipo de erro retornado quando a análise falha.
O operador ? só pode ser usado em funções que retornam um Result (ou Option), pois ele precisa ser capaz de retornar um erro.
Desafio
FácilVocê receberá duas entradas. A primeira entrada é uma string que deve ser analisada como um inteiro, e a segunda entrada é outra string que também deve ser analisada como um inteiro. Crie uma função chamada add_numbers que receba duas fatias de strings como parâmetros e retorne um Result<i32, std::num::ParseIntError>. Dentro da função, use o operador ? para analisar ambas as strings e retorne a soma delas envolvida em Ok. Chame a função com as duas entradas e trate o resultado usando match.
Requisitos:
- Leia a primeira entrada (primeiro número como string) e remova os espaços em branco
- Leia a segunda entrada (segundo número como string) e remova os espaços em branco
- Crie uma função
add_numbersque receba dois parâmetros&stre retorneResult<i32, std::num::ParseIntError> - Dentro da função, analise a primeira string como
i32usando o operador? - Analise a segunda string como
i32usando o operador? - Retorne
Ok(sum), em que sum é a soma dos dois números analisados - Chame a função com as duas strings de entrada
- Use uma expressão
matchpara tratar oResult - No braço
Ok(value), imprima:Sum: [value] - No braço
Err(_), imprima:Parsing error
Entrada:
- Primeira linha: uma string que representa um número (por exemplo,
15) - Segunda linha: uma string que representa outro número (por exemplo,
27)
Saída:
- Se ambas as strings forem números válidos:
Sum: [result] - Se alguma das strings não puder ser analisada:
Parsing error
Experimente você mesmo
use std::io;
// TODO: Crie a função add_numbers aqui
// Ela deve receber dois parâmetros &str e retornar Result<i32, std::num::ParseIntError>
fn main() {
// Lê a primeira entrada
let mut input1 = String::new();
io::stdin().read_line(&mut input1).expect("Failed to read line");
let input1 = input1.trim();
// Lê a segunda entrada
let mut input2 = String::new();
io::stdin().read_line(&mut input2).expect("Failed to read line");
let input2 = input2.trim();
// TODO: Chame add_numbers com input1 e input2
// TODO: Use match para tratar o Result
// Imprima "Sum: [value]" para Ok(value)
// Print "Parsing error" for Err(_)
}Esta lição inclui um quiz rápido. Comece a lição para respondê-lo e acompanhar seu progresso.
Todas as lições de Lógica & Fluxo
1Fluxo de Controle Avançado
A Expressão 'match'Correspondência de Múltiplos ValoresCorrespondência de IntervalosA Expressão 'if let'Loops como ExpressõesRecapitulação - Parser de Comandos Simples4Agrupando Dados com Structs
O que é uma Struct?Visão Geral de StructsAcessando Campos de uma StructStructs MutáveisStructs como Parâmetros de FunçãoTuple StructsRecapitulação - Criando uma Struct Book7Tratando Erros com 'Result'
O que é um 'Result'?Usando 'match' com 'Result'is_ok() e is_err()Atalhos: unwrap e expectO Operador de Interrogação '?'Parsing de Strings para NúmerosRecapitulação - Função de Divisão Segura2Introdução a Vetores
O que é um Vetor?Criando um VetorAdicionando Elementos com pushAcessando Elementos do VetorIterando sobre um VetorIteração MutávelRemovendo ElementosRecapitulação - Rastreador de Pontuação Básico5Pares Chave-Valor com Hash Maps
O que é um Hash Map?Criando um Hash MapInserindo Pares Chave-ValorAcessando ValoresIterando sobre um Hash MapAtualizando um ValorRemovendo um ParRecapitulação - Contador de Palavras8Projeto: Inventário Simples de Itens
Configuração do ProjetoAdicionando um ItemVerificando o EstoqueVendendo um ItemJuntando tudo3Lista de Tarefas via Linha de Comando
Configuração do ProjetoAdicionando uma TarefaVisualizando Todas as TarefasRemovendo uma TarefaCódigo FinalPratique por conta própria: Compilador de Rust online