Desafio Rust
Cadeia de operações com Option
Enunciado
Implemente calcular que recebe dois Option<i32> e retorna Option<i32>:
- Se ambos forem
Some, some os valores, dobre o resultado e, se o total for maior que 20, subtraia 5. - Se qualquer um for
None, retorneNone. Useand_thenemappara encadear as operações.
Requisitos
- A função deve retornar
Option<i32>. - Deve usar
and_thenpara combinar os doisOption. - Deve usar
mappara dobrar e subtrair condicionalmente. - Imprima o resultado para
(Some(10), Some(5)),(Some(3), Some(4))e(None, Some(7)).
Código inicial
fn calcular(a: Option<i32>, b: Option<i32>) -> Option<i32> {
// complete aqui
}
fn main() {
println!("{:?}", calcular(Some(10), Some(5)));
println!("{:?}", calcular(Some(3), Some(4)));
println!("{:?}", calcular(None, Some(7)));
}
Saída esperada
Some(25)
Some(14)
None
Ver dica
Comece com a.and_then(|x| b.map(|y| x + y)) para somar os dois valores. Depois encadeie map para dobrar e uma verificação condicional.
Mostrar solução
fn calcular(a: Option<i32>, b: Option<i32>) -> Option<i32> {
// Combina os dois Options: se ambos Some, soma; senão None
a.and_then(|x| b.map(|y| x + y))
.map(|soma| soma * 2) // dobra o resultado
.map(|dobro| if dobro > 20 { dobro - 5 } else { dobro }) // subtrai 5 se > 20
}
fn main() {
println!("{:?}", calcular(Some(10), Some(5))); // Some(25)
println!("{:?}", calcular(Some(3), Some(4))); // Some(14)
println!("{:?}", calcular(None, Some(7))); // None
}
Passo a passo
a.and_then(|x| b.map(|y| x + y))verifica seaéSome. Se for, usab.mappara combinar comb. SebforNone, o resultado éNone.- O primeiro
maprecebe a soma e multiplica por 2, retornando o dobro. - O segundo
mapaplica a condição: se o dobro for maior que 20, subtrai 5; senão, mantém. - Para
(Some(10), Some(5)): soma 15, dobro 30, 30 > 20, então 30 - 5 = 25 →Some(25). - Para
(Some(3), Some(4)): soma 7, dobro 14, 14 ≤ 20, então 14 →Some(14). - Para
(None, Some(7)):aéNone, entãoand_thenretornaNoneimediatamente.
Por que funciona
and_then permite encadear operações que retornam Option sem aninhar. O primeiro and_then combina os dois Option em um único Option<i32>. Os map subsequentes transformam o valor interno, propagando None se a cadeia já estiver quebrada. Isso mantém o código linear e seguro.
Erros comuns
- Usar
mapno lugar deand_thenpara combinaraeb:a.map(|x| b.map(|y| x + y))resultaria emOption<Option<i32>>. - Esquecer de tratar o caso
Noneno final: como usamosmapencadeado, oNoneé propagado automaticamente, mas se usássemosunwrapcausaria panic. - Lógica condicional invertida:
if dobro > 20 { dobro } else { dobro - 5 }daria resultados errados.
Outra forma de resolver
Usar match para combinar os dois Options:
match (a, b) {
(Some(x), Some(y)) => {
let dobro = (x + y) * 2;
Some(if dobro > 20 { dobro - 5 } else { dobro })
}
_ => None,
}
Prefira and_then/map para cadeias longas; match é mais claro para poucos casos.
Saída esperada
Some(25)
Some(14)
None