元組是存放多種不同類型數值的集合。元組透過圓括號 () 建立,每一個元組本身都是獨立的值,其型別標記寫作 (T1, T2, ...),其中 T1、T2 代表元組內各成員的型別。函式可利用元組回傳多個結果,因為單一個元組能夠承載任意數量的資料。
1 元組可作為函式參數、函式回傳值
// 元組既可以用作函式傳入參數,也可以用作函式回傳值
fn reverse(pair: (i32, bool)) -> (bool, i32) {
// let 可將元組內部成員解構綁定至獨立變數
let (int_param, bool_param) = pair;
// 回傳順序交換後的新元組
(bool_param, int_param)
}
fn main(){
// (12, true) 是完整的二元元組,作為單一參數傳入
let res = reverse((12, true));
// 使用 .0 索引取得回傳元組的第一個元素
println!("{}", res.0);
}Code language: JavaScript (javascript)
編譯與執行結果
E:\rustdemo\demo>rustc demo.rs
E:\rustdemo\demo>demo
trueCode language: JavaScript (javascript)
2 元組結構體(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)
元組式結構體:結構體名稱後緊接圓括號 + 型別清單,無具名欄位,僅透過順序區分元素;
#[derive(Debug)] 衍生巨集:自動為結構體實作 Debug 特徵,支援使用 {:?} 印出除錯資訊;
Matrix(f32,f32,f32,f32) 本質是包裝四個浮點數的特殊元組。
執行過程會出現一則警告,可直接忽略
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 多型別混合長元組 + 下標索引取值
先看範例
fn main(){
// 包含多種不同資料型別的長元組
let long_tuple = (1u8, 2u16, 3u32, 4u64,
-1i8, -2i16, -3i32, -4i64,
0.1f32, 0.2f64,
'a', true);
// 可透過元組下標索引取出內部數值
println!("Long tuple first value: {}", long_tuple.0);
println!("Long tuple second value: {}", long_tuple.1);
}Code language: JavaScript (javascript)
允許同時存放不同型別資料(無符號整數、有符號整數、浮點數、字元、布林值可共存);
元組索引語法:元組變數.數字,索引從 0 開始;
.0取得第一個元素,.1取得第二個元素;- 依此類推……
索引只能寫固定數字常值,不能使用變數作為索引。
以下為尚未整理完的內容——
2. 元組結構體(Tuple Struct)定義
// 下方結構體作為課後練習使用
#[derive(Debug)]
struct Matrix(f32, f32, f32, f32);
Code language: PHP (php)
配套知識點
- 元組式結構體:結構體名稱後緊跟圓括號,括號內為型別清單,沒有欄位名稱,僅依靠順序區分元素;
#[derive(Debug)]衍生巨集:自動為結構體實作Debug特徵,支援使用{:?}印出除錯資訊;Matrix(f32,f32,f32,f32)本質是包裝四個浮點數的特殊元組。
下方為完整範例
#[derive(Debug)]
struct Matrix(f32, f32, f32, f32);
fn main() {
// 1. 建立實例
let mat = Matrix(1.0, 2.0, 3.0, 4.0);
// 2. 列印(需加上 #[derive(Debug)] 才能使用 {:?})
println!("矩陣實例: {:?}", mat);
// 3. 存取內部元素:使用 .索引
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. 解構取值
// Matrix(m0, m1, m2, m3) 屬於解構模式比對,m0/m1/m2/m3 為自訂暫存變數,用來接收結構體內四個元組成員的值。
let Matrix(m0, m1, m2, m3) = mat;
println!("解構:{} {} | {} {}", m0, m1, m2, m3);
// 5. 可變矩陣,使用 mut 修改元素
let mut mat_mut = Matrix(0.0, 0.0, 0.0, 0.0);
mat_mut.0 = 10.0;
mat_mut.3 = 99.0; // 可修改數值
println!("可變矩陣: {:?}", mat_mut);
}Code language: PHP (php)
執行結果
E:\rustdemo\demo>demo
矩陣實例: Matrix(1.0, 2.0, 3.0, 4.0)
a=1, b=2, c=3, d=4
解構:1 2 | 3 4
可變矩陣: Matrix(10.0, 0.0, 0.0, 99.0)
3. 多型別混合長元組 + 下標索引取值
fn main() {
// 包含多種不同資料型別的長元組
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.
// 可透過元組下標索引取出內部數值
println!("Long tuple first value: {}", long_tuple.0);
println!("Long tuple second value: {}", long_tuple.1);
}
Code language: JavaScript (javascript)
執行結果
E:\rustdemo\demo>demo
Long tuple first value: 1
Long tuple second value: 2
重點整理
- 元組核心特性:允許同時存放不同型別資料(無符號整數、有符號整數、浮點數、字元、布林值可共存);
- 元組索引語法:
元組變數.數字,索引從 0 開始;.0取得第一個元素,.1取得第二個元素;
- 索引只能寫固定數字常值,不能使用變數作為索引。
4. 元組巢狀嵌套
fn main() {
// 元組的成員本身也可以是元組,支援巢狀嵌套
let tuple_of_tuples = ((1u8, 2u16, 2u32), (4u64, -1i8), -2i16);
// 元組支援除錯列印
println!("tuple of tuples: {:?}", tuple_of_tuples);
// 連續使用兩層 . 取值
println!("tuple of tuples: {:?}", tuple_of_tuples.0.1); // 輸出 2
}
Code language: JavaScript (javascript)
輸出結果
E:\rustdemo\demo>demo
tuple of tuples: ((1, 2, 2), (4, -1), -2)
tuple of tuples: 2
重點整理
- 支援多層元組巢狀嵌套,外層元組的元素可為子元組;
- 元素數量≤12 的元組會自動實作
Debug特徵,使用格式化符{:?}可直接完整列印內容。
5. 超長元組列印限制(編譯錯誤)
fn main() {
// 元素數量超過12個的超長元組無法直接使用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);
// 提示:取消註解上方兩行程式碼,即可看見編譯器報錯
}
Code language: JavaScript (javascript)
編譯錯誤訊息
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)
重點整理
Rust 標準函式庫僅為元素數量 0~12 的元組自動衍生 Debug 特徵;
元素個數>12 的元組沒有內建 Debug 實作,直接使用 {:?} 列印會造成編譯失敗。
讀者可把上面的數字13刪除後重新測試,觀察是否不再報錯
6. 呼叫帶元組參數的函式、觀察交換後結果
// 元組既可以用作函式傳入參數,也可以用作函式回傳值
fn reverse(pair: (i32, bool)) -> (bool, i32) {
// let 可將元組內部成員解構綁定至獨立變數
let (int_param, bool_param) = pair;
// 回傳順序交換後的新元組
(bool_param, int_param)
}
fn main() {
let pair = (1, true);
println!("Pair is {:?}", pair);
println!("The reversed pair is {:?}", reverse(pair)); //呼叫上方reverse函式進行交換
}Code language: JavaScript (javascript)
執行結果
E:\rustdemo\demo>demo
Pair is (1, true)
The reversed pair is (true, 1)Code language: JavaScript (javascript)
重點整理
- 一般二元元組可直接作為引數傳入接收元組型別的函式;
- 函式會回傳全新元組,原始元組
pair不會被修改。
7. 單元素元組特殊逗號規則(易踩坑重點)
fn main() {
// 建立單元素元組時必須加上逗號,用以區分僅用括號包圍的一般常值
println!("One element tuple: {:?}", (5u32,));
println!("Just an integer: {:?}", (5u32));
}Code language: JavaScript (javascript)
重點整理
(5u32,):末尾帶逗號,為合法單元素元組,型別為(u32,);(5u32):無逗號,僅等同一般數字5u32,只是使用括號包覆,並非元組;- 逗號是區分單元素元組與括號運算式的唯一標記。
8. 完整解構多元元組(參考上方範例)
// 元組可完整解構,一次綁定多個變數
let tuple = (1, "hello", 4.5, true);
let (a, b, c, d) = tuple;
println!("{:?}, {:?}, {:?}, {:?}", a, b, c, d);
Code language: JavaScript (javascript)
重點整理
- 任意長度的元組皆可整體解構,左側變數數量必須與元組元素數量完全一致;
- 解構後各變數分別對應元組相同位置的數值,可單獨使用。
9. 元組結構體實例化與 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)
重點整理
- 元組結構體實例化語法:
結構體名(值1, 值2, ...); - 加入
#[derive(Debug)]後,結構體支援{:?}除錯列印。
Previous: 字面量與運算子