Médio Rust

Contador com FnMut

Enunciado

Implemente uma função executar_duas_vezes que recebe uma closure mutável e a chama duas vezes, retornando a soma dos resultados. Use uma closure que incrementa um contador interno e retorna o novo valor. Imprima a soma final.

Requisitos

  • A função executar_duas_vezes deve aceitar F: FnMut() -> i32.
  • A closure deve capturar uma variável mutável e incrementá-la a cada chamada.
  • O programa deve imprimir a soma dos dois retornos.

Código inicial

fn executar_duas_vezes<F: FnMut() -> i32>(mut f: F) -> i32 {
    f() + f()
}

fn main() {
    let mut contador = 0;
    // Complete aqui: crie a closure e chame executar_duas_vezes
}

Saída esperada

3
Ver dica

A closure deve ser || { contador += 1; contador }. Lembre-se de declarar contador como mut.

Mostrar solução
fn executar_duas_vezes<F: FnMut() -> i32>(mut f: F) -> i32 {
    f() + f()
}

fn main() {
    let mut contador = 0;
    // Closure que captura contador por empréstimo mutável
    let mut incrementar = || {
        contador += 1;
        contador
    };
    let soma = executar_duas_vezes(&mut incrementar);
    println!("{}", soma);
}

Passo a passo

  1. Definimos executar_duas_vezes que recebe mut f: F onde F: FnMut() -> i32.
  2. Dentro de main, criamos contador mutável iniciado em 0.
  3. Criamos a closure incrementar que captura contador por empréstimo mutável, incrementa e retorna o novo valor.
  4. Chamamos executar_duas_vezes passando &mut incrementar (a função precisa de uma referência mutável à closure).
  5. A função chama a closure duas vezes: primeiro retorna 1, depois 2, e soma 3.
  6. Imprimimos a soma.

Por que funciona

A closure modifica contador, então captura por empréstimo mutável, implementando FnMut. A função executar_duas_vezes aceita FnMut e pode chamá-la múltiplas vezes. Passamos &mut incrementar porque a função precisa de uma referência mutável para chamar a closure que muta o ambiente.

Erros comuns

  • Declarar contador sem mut: a closure não poderia modificar, gerando erro de compilação.
  • Passar incrementar sem &mut: a função espera F: FnMut, mas passar por valor moveria a closure; usar &mut permite empréstimo mutável.
  • Esquecer de declarar f como mut na assinatura de executar_duas_vezes: sem isso, não é possível chamar f() que requer &mut self.

Outra forma de resolver

Poderia usar move para capturar contador por valor, mas aí o contador seria movido para dentro da closure e não poderia ser usado fora. A versão com empréstimo mutável é mais flexível.

Saída esperada

3