Introdução
Uma variável armazena um valor, mas muitos programas precisam de uma lista ordenada cujo tamanho possa mudar. O Vec<T> do Rust é uma sequência expansível: cada elemento tem o tipo T, os valores mantêm sua ordem e o vetor é proprietário de seus elementos.
Você criará uma lista de pedidos de um café, lerá com segurança uma posição, percorrerá todos os pedidos sem consumir a lista e atualizará cada string armazenada por meio de referências mutáveis.
Criar e expandir um vetor
Nesta etapa, você adicionará três strings próprias a um vetor inicialmente vazio.
Entre no projeto preparado e abra o código-fonte:
cd /home/labex/project/cafe-orders
nano src/main.rs
A declaração Vec<String> significa “um vetor cujos elementos são valores String próprios”. Essa é a mesma notação com colchetes angulares usada para contêineres que você viu em Option<u32>: aqui, o tipo do elemento contido é String. Você aprenderá a definir tipos reutilizáveis desse tipo na Lab posterior sobre genéricos. Vec::new() cria um vetor vazio. A variável é declarada com mut porque adicionar elementos altera o vetor.
Substitua o comentário da Etapa 1 por três chamadas a push:
orders.push(String::from("Latte"));
orders.push(String::from("Tea"));
orders.push(String::from("Cake"));
push adiciona um elemento ao final, preservando a ordem de inserção. Salve com Ctrl+O, pressione Enter e saia com Ctrl+X. Verifique e execute:
cargo check
cargo run --quiet
A saída deverá ser:
Order count: 3
Orders: ["Latte", "Tea", "Cake"]
len() informa que há três elementos. O marcador :? usa a formatação de depuração do Rust para exibir o vetor completo, incluindo as aspas das strings.
Ler uma posição com segurança
Nesta etapa, você lerá a segunda posição do vetor sem correr o risco de um panic por acesso fora dos limites.
As posições de um vetor começam em zero, portanto o índice 1 se refere ao segundo pedido. O método get retorna um Option<&String>: Some contém uma referência compartilhada quando a posição existe, e None representa uma posição ausente. A referência permite ler o elemento enquanto o vetor continua sendo seu proprietário.
Abra o código-fonte:
nano src/main.rs
Substitua o comentário da Etapa 2 por:
match orders.get(1) {
Some(order) => println!("Second order: {order}"),
None => println!("Second order: missing"),
}
Esse código lê o elemento sem mover sua String para fora do vetor. Salve e saia, depois execute:
cargo run --quiet
Uma nova linha final deverá aparecer:
Second order: Tea
Essa linha comprova que a posição 1 existe e que a ordem de inserção foi preservada.
Percorrer usando uma referência compartilhada
Nesta etapa, você percorrerá todos os pedidos e manterá o vetor disponível depois disso.
Escrever &orders toma emprestado o vetor em vez de movê-lo para dentro do loop for. Portanto, cada valor do loop é uma referência compartilhada a uma String armazenada.
Abra o código-fonte:
nano src/main.rs
Substitua o comentário da Etapa 3 por este loop e pela verificação seguinte:
for order in &orders {
println!("Queued: {order}");
}
println!("Stored after display: {}", orders.len());
Salve e saia, depois execute:
cargo run --quiet
As novas linhas deverão ser:
Queued: Latte
Queued: Tea
Queued: Cake
Stored after display: 3
A contagem final pode ser usada depois do loop porque o loop tomou o vetor emprestado e devolveu cada referência compartilhada antes de continuar.
Atualizar por meio de referências mutáveis
Nesta etapa, você tomará cada elemento do vetor emprestado de forma mutável e o atualizará no próprio local antes da execução do loop de exibição.
Somente uma referência mutável a um valor pode estar ativa por vez. Um loop for sobre &mut orders segue essa regra ao fornecer uma referência mutável a um elemento, usá-la durante a iteração atual e depois passar ao elemento seguinte.
Abra o código-fonte:
nano src/main.rs
Substitua o comentário da Etapa 4 por:
for order in &mut orders {
order.push_str(" - ready");
}
push_str adiciona texto emprestado a cada String própria. O Rust usa automaticamente a String mutável por trás de cada referência nessa chamada de método.
Salve e saia, depois verifique e execute:
cargo check
cargo run --quiet
A saída completa deverá ser:
Order count: 3
Orders: ["Latte", "Tea", "Cake"]
Second order: Tea
Queued: Latte - ready
Queued: Tea - ready
Queued: Cake - ready
Stored after display: 3
As linhas atualizadas da fila comprovam que todos os elementos foram alterados no próprio local. A contagem final comprova que o vetor ainda é proprietário das mesmas três strings.
Resumo
Você criou e expandiu um Vec<String>, acessou uma posição com segurança usando get, percorreu o vetor sem consumi-lo e atualizou cada elemento por meio de referências mutáveis.


