let v = vec!['a', 'b', 'c'];
for (index, value) in v.iter().enumerate() {
println!("{} is at index {}", value, index);
}
// a is at index 0// b is at index 1// c is at index 2
fnmain() {
let x = Some(5);
let y = 10;
match x {
// 50だったよSome(50) => println!("Got 50"),
// マッチしたよSome(y) => println!("Matched, y = {:?}", y),
// 既定のケース
_ => println!("Default case, x = {:?}", x),
}
// 最後にはx = {}, y = {}println!("at the end: x = {:?}, y = {:?}", x, y);
}
複数のパターン
match式では|記法で複数のパターンに合致させることができる
let x = 1;
match x {
// 1か21 | 2 => println!("one or two"),
// 33 => println!("three"),
// なんでも
_ => println!("anything"),
}
..=で値の範囲に合致させる
..=記法は限界値を含む値の範囲にマッチさせることができる
古いバージョンでは"..."
..=は数値かchar型にのみ使うことが出来る
let x = 5;
match x {
// 1から5まで1 ..= 5 => println!("one through five"),
// それ以外
_ => println!("something else"),
}
let x = 'c';
match x {
// ASCII文字前半'a' ... 'j' => println!("early ASCII letter"),
// ASCII文字後半'k' ... 'z' => println!("late ASCII letter"),
// それ以外
_ => println!("something else"),
}
分配して値を分解する
構造体,enum,タプルはそれらを構成する型にパターンマッチで分解することが出来る
以降ではパターンマッチで分配する方法を述べる
ここでは分解なのに,以降は分配と書かれている
分解→destructing to break apart,分配→destructing
構造体を分配する
構造体pの要素xとyを,aとbに分配する
structPoint {
x: i32,
y: i32,
}
fnmain() {
let p = Point { x: 0, y: 7 };
let Point { x: a, y: b } = p;
// let Point { a, b } = p; でもOK// let Point { y: b, x: a } = p; でもOKassert_eq!(0, a);
assert_eq!(7, b);
}
enumを分配する
enumも構造体と同様に分配できる
enumMessage {
Quit,
Coordinate(i32, i32),
}
fnmain() {
let msg = Message::Coordinate(10, 5);
match msg {
Message::Quit => {
println!("The Quit variant has no data to destructure.")
},
Message::Coordinate(x, y) => {
println!("Change the coordinate to x {} and y {}", x, y)
}
}
}
参照を分配する
ある型への参照を,その型を構成する型への参照に分配できる
let points = vec![
Point { x: 0, y: 0 },
Point { x: 1, y: 5 },
Point { x: 10, y: -3 },
];
let sum_of_squares: i32 = points
.iter()
.map(|&Point { x, y }| x * x + y * y)
.sum();
構造体とタプルを分配する
構造体とタプルが混ざった型ももちろん分解できる
let ((feet, inches), Point {x, y}) = ((3, 10), Point { x: 3, y: -10 });
パターンの値を無視する
パターンの中で値を無視する方法は_と..
_で値全体を無視する
_にマッチした値は無視される
fnfoo(_: i32, y: i32) {
// このコードは、y引数を使うだけです: {}println!("This code only uses the y parameter: {}", y);
// "This code only uses the y parameter: 4"と表示される
}
fnmain() {
foo(3, 4);
}
error: `..` can only be used once per tuple or tuple struct pattern
(エラー: `..`は、タプルやタプル構造体パターン1つにつき、1回しか使用できません)
--> src/main.rs:5:22
|
5 | (.., second, ..) => {
| ^^
refとref mutでパターンに参照を生成する
通常のパターンマッチでは,値を束縛される際にムーブされる
マッチさせる値の所有権を失いたくない場合はrefで参照にマッチするようにする
可変参照にマッチさせたい場合はmut refを使う
let robot_name = Some(String::from("Bors"));
match robot_name {
Some(ref name) => println!("Found a name: {}", name),
None => (),
}
println!("robot_name is: {:?}", robot_name);
マッチガードで追加の条件式
マッチガードはmatchアームのパターンの後に指定されるif条件
最初のパターンに合致すると,次のif条件で比較する
let num = Some(4);
match num {
// 5未満です: {}Some(x) if x < 5 => println!("less than five: {}", x),
Some(x) => println!("{}", x),
None => (),
}
@束縛
ある範囲に値がマッチするかを検査する
enumMessage {
Hello { id: i32 },
}
let msg = Message::Hello { id: 5 };
match msg {
Message::Hello { id: id_variable @ 3...7 } => {
// 範囲内のidが見つかりました: {}println!("Found an id in range: {}", id_variable)
},
Message::Hello { id: 10...12 } => {
// 別の範囲内のidが見つかりましたprintln!("Found an id in another range")
},
Message::Hello { id } => {
// それ以外のidが見つかりましたprintln!("Found some other id: {}", id)
},
}