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, retorne None. Use and_then e map para encadear as operações.

Requisitos

  • A função deve retornar Option<i32>.
  • Deve usar and_then para combinar os dois Option.
  • Deve usar map para 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

  1. a.and_then(|x| b.map(|y| x + y)) verifica se a é Some. Se for, usa b.map para combinar com b. Se b for None, o resultado é None.
  2. O primeiro map recebe a soma e multiplica por 2, retornando o dobro.
  3. O segundo map aplica a condição: se o dobro for maior que 20, subtrai 5; senão, mantém.
  4. Para (Some(10), Some(5)): soma 15, dobro 30, 30 > 20, então 30 - 5 = 25 → Some(25).
  5. Para (Some(3), Some(4)): soma 7, dobro 14, 14 ≤ 20, então 14 → Some(14).
  6. Para (None, Some(7)): a é None, então and_then retorna None imediatamente.

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 map no lugar de and_then para combinar a e b: a.map(|x| b.map(|y| x + y)) resultaria em Option<Option<i32>>.
  • Esquecer de tratar o caso None no final: como usamos map encadeado, o None é propagado automaticamente, mas se usássemos unwrap causaria 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