Médio Rust

Empréstimo mutável e escopo

Enunciado

Crie uma função dobrar_valores que recebe uma referência mutável a um Vec<i32> e multiplica todos os elementos por 2. No main, crie um vetor, chame a função e imprima o vetor modificado. Garanta que não haja empréstimos simultâneos conflitantes.

Requisitos

  • A função deve aceitar &mut Vec<i32> e modificar o vetor no lugar.
  • O main deve declarar o vetor como mutável (let mut).
  • Após a chamada, o vetor original deve refletir as modificações.
  • A saída deve mostrar o vetor antes e depois.

Código inicial

fn dobrar_valores(v: &mut Vec<i32>) {
    // complete aqui
}

fn main() {
    let mut numeros = vec![1, 2, 3, 4];
    // chame a função e imprima
}

Saída esperada

Antes: [1, 2, 3, 4]
Depois: [2, 4, 6, 8]
Ver dica

Use um loop for com iter_mut() para obter referências mutáveis a cada elemento.

Mostrar solução
fn dobrar_valores(v: &mut Vec<i32>) {
    // iter_mut dá &mut i32 para cada elemento
    for elemento in v.iter_mut() {
        *elemento *= 2; // desreferencia para modificar o valor
    }
}

fn main() {
    let mut numeros = vec![1, 2, 3, 4];
    println!("Antes: {:?}", numeros);
    dobrar_valores(&mut numeros); // empréstimo mutável
    println!("Depois: {:?}", numeros);
}

Passo a passo

  1. A função dobrar_valores recebe v: &mut Vec<i32>, um empréstimo mutável do vetor.
  2. v.iter_mut() cria um iterador que produz referências mutáveis (&mut i32) para cada elemento.
  3. No loop, elemento é do tipo &mut i32. Para modificar o valor apontado, usamos *elemento (desreferenciação).
  4. *elemento *= 2 multiplica o valor original por 2 e armazena de volta.
  5. No main, let mut numeros permite que o vetor seja emprestado mutavelmente.
  6. &mut numeros cria a referência mutável passada para a função. Durante a chamada, não pode haver outros empréstimos ativos.
  7. Após a função retornar, o empréstimo termina e numeros pode ser impresso normalmente.

Por que funciona

O borrow checker garante que, enquanto &mut numeros estiver ativo, nenhuma outra referência (mutável ou imutável) ao mesmo vetor exista. Isso impede data races. Como o empréstimo é liberado ao final da chamada, o main recupera o acesso exclusivo.

Erros comuns

  • Esquecer mut na declaração: let numeros = vec![1,2,3]; e depois &mut numeros causa erro cannot borrow as mutable.
  • Tentar usar o vetor durante o empréstimo mutável:
    let r = &mut numeros;
    println!("{:?}", numeros); // erro: cannot borrow `numeros` as immutable
    dobrar_valores(r);
    
    O compilador impede leitura enquanto há empréstimo mutável ativo.
  • Não desreferenciar ao modificar: escrever elemento *= 2; sem * causa erro cannot assign to elemento because it is a & reference.

Outra forma de resolver

Usar for elemento in v (sem iter_mut) também funciona porque &mut Vec implementa IntoIterator produzindo &mut i32:

fn dobrar_valores(v: &mut Vec<i32>) {
    for elemento in v {
        *elemento *= 2;
    }
}

Saída esperada

Antes: [1, 2, 3, 4]
Depois: [2, 4, 6, 8]