Propagando Erros
Parte da seção Lógica e Fluxo do Journey de Swift da Coddy — lição 47 de 56.
Uma função que lança erros pode chamar outras funções que lançam erros. O erro propaga-se até o do/catch mais próximo automaticamente, sem a necessidade de relançamento manual.
enum AuthError: Error { case badUser, badPass }
func loadUser(_ name: String) throws -> String {
if name.isEmpty { throw AuthError.badUser }
return name
}
func login(_ name: String, _ pass: String) throws -> String {
let u = try loadUser(name) // encaminha o erro
if pass.count < 4 { throw AuthError.badPass }
return "hello \(u)"
}
do {
print(try login("", "abcd"))
} catch AuthError.badUser {
print("missing user")
} catch AuthError.badPass {
print("weak password")
}Leia de cima para baixo: login chama loadUser com try. Se loadUser lançar um erro, o erro ignora o corpo de login e cai no catch externo. Você escreve cada etapa para falhar rapidamente e deixar que quem chama decida o que fazer.
Desafio
MédioConstrua um pequeno pipeline de duas etapas que lançam erros (throwing steps).
Defina StepError: Error com dois casos: negative, tooBig.
Defina parseSafe(_ s: String) throws -> Int: lança .negative quando o inteiro analisado for menor que 0, caso contrário, o retorna. (Assuma que a entrada é analisada corretamente, você já tratou isso em outro lugar.)
Defina capStrict(_ n: Int) throws -> Int: lança .tooBig quando n > 100, caso contrário, retorna n.
Defina processStep(_ s: String) throws -> Int que chama parseSafe e depois capStrict, permitindo que qualquer erro se propague.
Leia uma única linha de entrada: uma lista de strings separadas por vírgulas. Para cada uma, chame processStep em um bloco do/catch e imprima uma linha:
ok: <n>em caso de sucessonegativequandoparseSafelançar errotoo bigquandocapStrictlançar erro
Para a entrada 10,-1,200,42, a saída é:
ok: 10
negative
too big
ok: 42Folha de consulta
Uma função que lança erros (throwing function) pode chamar outras funções que lançam erros com try. Os erros se propagam automaticamente até o do/catch mais próximo:
enum AuthError: Error { case badUser, badPass }
func loadUser(_ name: String) throws -> String {
if name.isEmpty { throw AuthError.badUser }
return name
}
func login(_ name: String, _ pass: String) throws -> String {
let u = try loadUser(name) // o erro se propaga se for lançado
if pass.count < 4 { throw AuthError.badPass }
return "hello \(u)"
}
do {
print(try login("", "abcd"))
} catch AuthError.badUser {
print("missing user")
} catch AuthError.badPass {
print("weak password")
}Se loadUser lançar um erro, a execução pula o restante de login e cai diretamente no catch externo. Não é necessário relançar o erro manualmente.
Experimente você mesmo
let parts = readLine()!.components(separatedBy: ",")
// TODO: enum StepError; parseSafe; capStrict; processStep;
// para cada parte, faça/tente processStep, capture cada ramificação, imprima
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 e Fluxo
1Strings a Fundo
Contagem e ÍndicesCase e TrimBusca em StringsDivisão e JunçãoSubstituindo SubstringsRecapitulação - Verificação de Nome de Usuário4Conjuntos
Criando ConjuntosUnião e InterseçãoSubtração e Diferença SimétricaSubconjunto e SuperconjuntoRecapitulação - Filtro de Tags7Projeto - Monitor de Hábitos
Visão Geral do ProjetoMarcar como Concluído10Projeto - Mecanismo de Quiz
Visão Geral do ProjetoFazer Perguntas2Intervalos e Strides
Fechado vs Meio-AbertoStrideMétodos de IntervaloIntervalos no SwitchRecapitulação - Grade de Calendário5Funções de Ordem Superior Parte 1
MapFilterReduceEncadeando map, filter, reduceRecapitulação - Estatísticas de Palavras3Dicionários
Declarando DicionáriosBusca OpcionalAtualizando DicionáriosIterando DicionáriosAgrupando ValoresRecapitulação - Inventário6Funções de Ordem Superior Parte 2
compactMapflatMapsorted(by:)Construindo PipelinesRecapitulação - Leaderboard9Tratamento de Erros
throws e Errordo, try, catchtry? e try!Propagando ErrosRecapitulação - Calculadora Segura