Uma tupla é uma coleção que armazena valores de vários tipos diferentes. Tuplas são criadas usando parênteses (). Cada tupla é um valor independente por si só, sua anotação de tipo é escrita como (T1, T2, ...), onde T1 e T2 representam o tipo de cada membro interno da tupla. Funções podem retornar vários resultados usando tuplas, pois uma única tupla pode conter uma quantidade arbitrária de dados.
1 Usar tuplas como parâmetros e valores de retorno de funções
// Tuplas podem ser usadas tanto como parâmetros de entrada quanto valores retornados por uma função
fn reverse(pair: (i32, bool)) -> (bool, i32) {
// let permite desestruturar membros da tupla e vinculá-los a variáveis separadas
let (int_param, bool_param) = pair;
// Retorna uma nova tupla com a ordem trocada
(bool_param, int_param)
}
fn main(){
// (12, true) é uma tupla binária completa, passada como um único parâmetro
let res = reverse((12, true));
// Usar o índice .0 para pegar o primeiro elemento da tupla retornada
println!("{}", res.0);
}Code language: JavaScript (javascript)
Resultado da compilação e execução
E:\rustdemo\demo>rustc demo.rs
E:\rustdemo\demo>demo
trueCode language: JavaScript (javascript)
2 Definição de Estrutura de Tupla (Tuple Struct)
#[derive(Debug)]
struct Matrix(f32, f32, f32, f32);
fn main(){
let matrix = Matrix(1.1, 1.2, 2.1, 2.2);
println!("{:?}", matrix);
}Code language: PHP (php)
Estrutura de tupla: o nome da estrutura vem seguido diretamente por parênteses + lista de tipos, sem campos nomeados; os elementos só são diferenciados pela ordem;
A macro derivada #[derive(Debug)]: implementa automaticamente a trait Debug para a estrutura, permitindo imprimir informações de depuração com {:?};
Matrix(f32,f32,f32,f32) é essencialmente uma tupla especial que envolve quatro números de ponto flutuante.
Um aviso aparecerá durante a execução e pode ser ignorado
E:\rustdemo\demo>rustc demo.rs
warning: fields `0`, `1`, `2`, and `3` are never read
--> demo.rs:2:15
|
2 | struct Matrix(f32, f32, f32, f32);
| ------ ^^^ ^^^ ^^^ ^^^
| |
| fields in this struct
|
= help: consider removing these fields
= note: `Matrix` has a derived impl for the trait `Debug`, but this is intentionally ignored during dead code analysis
= note: `#[warn(dead_code)]` (part of `#[warn(unused)]`) on by default
warning: 1 warning emitted
E:\rustdemo\demo>demo
Matrix(1.1, 1.2, 2.1, 2.2)Code language: JavaScript (javascript)
3 Tuplas longas com tipos mistos + pegar valores por índice
Veja o exemplo primeiro
fn main(){
// Tupla longa contendo vários tipos de dados diferentes
let long_tuple = (1u8, 2u16, 3u32, 4u64,
-1i8, -2i16, -3i32, -4i64,
0.1f32, 0.2f64,
'a', true);
// Valores internos podem ser extraídos usando índices da tupla
println!("Long tuple first value: {}", long_tuple.0);
println!("Long tuple second value: {}", long_tuple.1);
}Code language: JavaScript (javascript)
Permite armazenar dados de tipos diferentes ao mesmo tempo (inteiros sem sinal, inteiros com sinal, floats, caracteres e booleanos podem coexistir);
Sintaxe de índice de tupla: variável_tupla.número, índices começam em 0;
.0pega o primeiro elemento,.1pega o segundo elemento;- e assim por diante…
Índices só aceitam literais numéricos fixos; variáveis não podem ser usadas como índice.
Parte não organizada abaixo——
2. Definição de Estrutura de Tupla (Tuple Struct)
// A estrutura abaixo é para exercícios após a aula
#[derive(Debug)]
struct Matrix(f32, f32, f32, f32);
Code language: PHP (php)
Pontos de conhecimento complementares
- Estrutura de tupla: o nome da estrutura é seguido por parênteses com lista de tipos dentro. Não há nomes de campos, os elementos são diferenciados apenas pela ordem;
- A macro derivada
#[derive(Debug)]: implementa automaticamente a traitDebugpara a estrutura, permitindo impressão de depuração com{:?}; Matrix(f32,f32,f32,f32)é essencialmente uma tupla especial que envolve quatro números de ponto flutuante.
Exemplo completo abaixo
#[derive(Debug)]
struct Matrix(f32, f32, f32, f32);
fn main() {
// 1. Criar instância
let mat = Matrix(1.0, 2.0, 3.0, 4.0);
// 2. Imprimir (é preciso #[derive(Debug)] para usar {:?})
println!("Instância da matriz: {:?}", mat);
// 3. Acessar elementos internos via .índice
let a = mat.0;
let b = mat.1;
let c = mat.2;
let d = mat.3;
println!("a={}, b={}, c={}, d={}", a, b, c, d);
// 4. Extrair valores por desestruturação
// Matrix(m0, m1, m2, m3) é um padrão de desestruturação. m0/m1/m2/m3 são nomes de variáveis temporais definidos por você, que recebem os valores dos quatro membros da tupla dentro da estrutura.
let Matrix(m0, m1, m2, m3) = mat;
println!("Desestruturação:{} {} | {} {}", m0, m1, m2, m3);
// 5. Matriz mutável, modificar elementos com mut
let mut mat_mut = Matrix(0.0, 0.0, 0.0, 0.0);
mat_mut.0 = 10.0;
mat_mut.3 = 99.0; // Valores podem ser alterados
println!("Matriz mutável: {:?}", mat_mut);
}Code language: PHP (php)
Resultado da execução
E:\rustdemo\demo>demo
Instância da matriz: Matrix(1.0, 2.0, 3.0, 4.0)
a=1, b=2, c=3, d=4
Desestruturação:1 2 | 3 4
Matriz mutável: Matrix(10.0, 0.0, 0.0, 99.0)
3 Tuplas longas com tipos mistos + pegar valores por índice
fn main() {
// Tupla longa contendo vários tipos de dados diferentes
let long_tuple = (1u8, 2u16, 3u32, 4u64,
-1i8, -2i16, -3i32, -4i64,
0.1f32, 0.2f64,
'a', true);
// Values can be extracted from the tuple using tuple indexing.
// Valores internos podem ser extraídos usando índices da tupla
println!("Long tuple first value: {}", long_tuple.0);
println!("Long tuple second value: {}", long_tuple.1);
}
Code language: JavaScript (javascript)
Resultado da execução
E:\rustdemo\demo>demo
Long tuple first value: 1
Long tuple second value: 2
Resumo
- Característica principal das tuplas: permite armazenar dados de tipos diferentes ao mesmo tempo (inteiros sem sinal, inteiros com sinal, floats, caracteres e booleanos podem coexistir);
- Sintaxe de índice de tupla:
variável_tupla.número, índices começam em 0;.0pega o primeiro elemento,.1pega o segundo elemento;
- Índices só aceitam literais numéricos fixos; variáveis não podem ser usadas como índice.
4 Tuplas aninhadas
fn main() {
// Os membros de uma tupla também podem ser tuplas, aninhamento é suportado
let tuple_of_tuples = ((1u8, 2u16, 2u32), (4u64, -1i8), -2i16);
// Tuplas suportam impressão de depuração
println!("tuple of tuples: {:?}", tuple_of_tuples);
// Usar dois pontos seguidos para imprimir valores
println!("tuple of tuples: {:?}", tuple_of_tuples.0.1); // Imprime 2
}
Code language: JavaScript (javascript)
Saída
E:\rustdemo\demo>demo
tuple of tuples: ((1, 2, 2), (4, -1), -2)
tuple of tuples: 2
Resumo
- Suporta aninhamento de tuplas em vários níveis; os elementos da tupla externa podem ser subtuplas;
- Tuplas com ≤12 elementos implementam automaticamente a trait
Debug, o especificador de formatação{:?}pode imprimir todo o conteúdo diretamente.
5 Restrição de impressão para tuplas muito longas (erro de compilação)
fn main() {
// Tuplas com mais de 12 elementos não podem ser impressas diretamente com Debug
let too_long_tuple = (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13);
println!("Too long tuple: {:?}", too_long_tuple);
// Dica: comente as duas linhas acima para ver o erro do compilador
}
Code language: JavaScript (javascript)
Erro de compilação
E:\rustdemo\demo>rustc demo.rs
error[E0277]: `({integer}, {integer}, {integer}, {integer}, {integer}, {integer}, {integer}, {integer}, {integer}, {integer}, {integer}, {integer}, {integer})` doesn't implement `Debug`
--> demo.rs:5:38
|
5 | println!("Too long tuple: {:?}", too_long_tuple);
| ---- ^^^^^^^^^^^^^^ `({integer}, {integer}, {integer}, {integer}, {integer}, {integer}, {integer}, {integer}, {integer}, {integer}, {integer}, {integer}, {integer})` cannot be formatted using `{:?}` because it doesn't implement `Debug`
| |
| required by this formatting parameter
|
= help: the trait `Debug` is not implemented for `({integer}, {integer}, {integer}, {integer}, {integer}, {integer}, {integer}, {integer}, {integer}, {integer}, {integer}, {integer}, {integer})`
= help: the following other types implement trait `Debug`:
()
(A, Z, Y, X, W, V, U, T)
(B, A, Z, Y, X, W, V, U, T)
(C, B, A, Z, Y, X, W, V, U, T)
(D, C, B, A, Z, Y, X, W, V, U, T)
(E, D, C, B, A, Z, Y, X, W, V, U, T)
(T,)
(U, T)
and 5 others
= note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info)
error: aborting due to 1 previous error
For more information about this error, try `rustc --explain E0277`.Code language: PHP (php)
Resumo
A biblioteca padrão do Rust só deriva automaticamente a trait Debug para tuplas com 0~12 elementos;
Tuplas com mais de 12 elementos não têm implementação nativa de Debug, imprimir diretamente com {:?} causará falha na compilação.
Você pode apagar o número 13 acima e testar para ver se o erro desaparece
6 Chamar funções com parâmetros de tupla e observar o resultado trocado
// Tuplas podem ser usadas tanto como parâmetros de entrada quanto valores retornados por uma função
fn reverse(pair: (i32, bool)) -> (bool, i32) {
// let permite desestruturar membros da tupla e vinculá-los a variáveis separadas
let (int_param, bool_param) = pair;
// Retorna uma nova tupla com a ordem trocada
(bool_param, int_param)
}
fn main() {
let pair = (1, true);
println!("Pair is {:?}", pair);
println!("The reversed pair is {:?}", reverse(pair)); // Chamar reverse para trocar a ordem
}Code language: JavaScript (javascript)
Resultado da execução
E:\rustdemo\demo>demo
Pair is (1, true)
The reversed pair is (true, 1)Code language: JavaScript (javascript)
Resumo
- Tuplas binárias normais podem ser passadas diretamente como argumentos para funções que aceitam tuplas;
- A função retorna uma tupla totalmente nova, a tupla original
pairnão é modificada.
7 Regra especial da vírgula para tuplas de um único elemento (ponto comum de erro)
fn main() {
// Ao criar uma tupla de um único elemento é obrigatório adicionar vírgula para diferenciar de literais comuns apenas envoltos por parênteses
println!("One element tuple: {:?}", (5u32,));
println!("Just an integer: {:?}", (5u32));
}Code language: JavaScript (javascript)
Resumo
(5u32,): com vírgula no final, é uma tupla válida de um único elemento, tipo(u32,);(5u32): sem vírgula, equivale apenas ao número comum5u32envolto por parênteses, não é uma tupla;- A vírgula é o único marcador que distingue tuplas de um elemento de expressões entre parênteses.
8 Desestruturação completa de tuplas com múltiplos elementos (veja acima)
// Tuplas podem ser totalmente desestruturadas para vincular várias variáveis de uma vez
let tuple = (1, "hello", 4.5, true);
let (a, b, c, d) = tuple;
println!("{:?}, {:?}, {:?}, {:?}", a, b, c, d);
Code language: JavaScript (javascript)
Resumo
- Tuplas de qualquer comprimento podem ser totalmente desestruturadas; a quantidade de variáveis à esquerda deve combinar exatamente com a quantidade de elementos da tupla;
- Após desestruturação, cada variável corresponde ao valor da mesma posição na tupla e pode ser usada separadamente.
9 Instanciação de estrutura de tupla e impressão Debug
#[derive(Debug)]
struct Matrix(f32, f32, f32, f32);
fn main() {
let matrix = Matrix(1.1, 1.2, 2.1, 2.2);
println!("{:?}", matrix);
}Code language: PHP (php)
Resumo
- Sintaxe de instanciação de estrutura de tupla:
NomeEstrutura(valor1, valor2, ...); - Ao adicionar
#[derive(Debug)], a estrutura suporta impressão de depuração via{:?}.