Se você é desenvolvedor Swift muito provavelmente já usou o tipo Result
em algum código.
Result
é um um Generic Enumeration, e nos auxiliara lidar com requisições que
podem dar certo - nos trazendo um valor de retorno, ou errado, resultando em um erro.
Ao realizar operações é bem comum que tenhamos no mínimo dois outputs; if-else
,
is nil or not
e success-failure
são bem familiares.
Você já parou pra pensar no porquê essa estrutura funciona tão bem?
No caso success-failure
, tem uma definição tal que:
enum Result<Success, Failure> where Failure : Error
Isto é, Result
é um enum
associado à dois tipos: Success
e Failure
, tal que
Failure
é do tipo Error
.
Ao utiliza-lo, garantimos que apenas 1 dos casos/contrutores será satisfeito. Ele funciona assim:
enum Result<Success, Failure> where Failure : Error {
case success(Success)
case failure(Failure)
}
O construtor succcess
está associado à um tipo Success
(Tipo Genérico),
que permite o reuso dessa estrutura pra diversos contextos. Já o construtor failure
está associado à um tipo Error
, que já é conhecido pelo Swift e também nos
permite uma customização de erros.
load { [weak self] result in
switch result {
case .success(let data):
self?.render(data)
case .failure(let error):
switch error {
case .networkUnavailable:
self?.showErrorView(withMessage: .offline)
case .timedOut:
self?.showErrorView(withMessage: .timedOut)
}
}
}
Algo parecido acontece com a estrutura do Optional
, que na documentação do Swift diz que:
Optionals say either “there is a value, and it equals x” or “there isn’t a value at all”.
Onde:
enum Optional<Wrapped> {
case none
case some(value: Wrapped)
}
E o mesmo pode ser usado para representar se um ícone usará uma URL ou uma imagem default:
typealias IconResult<URL, UIImage> {
case hasURL(URL)
case defaultIcon(UIImage)
}
Essa estrutura comum à todos esses exemplos se chama Either
e pode ser definida assim:
type Either<A: Type, B: Type> {
left(value: A),
right(value: B)
}
As utilidades são tantas que podemos até mesmo definir o que é um número e o que é uma lista!
type Nat {
zero
succ(pred: Nat)
}
type List<A: Type> {
nil
cons(head: A, tail: List<A>)
}
E aí, ficou curioso(a) em saber mais sobre Result
e Either
? Aqui vão algumas
sugestões de leitura sobre o assunto:
Caso queira ir além e se aprofundar no uso de Enums
, recomendo estudar sobre Algebraic Data Type (ADT).