❓
Rust 所有権クイズ!
はじめに
こんにちは、ファスト株式会社のYTです!
突然ですが、Rustクイズです!
以下のコードのうち、ターミナルにこんにちは!と出力されるのはどれでしょうか?
1: Some(greet)
fn main() {
let greet = Some(String::from("こんにちは!"));
match greet {
Some(greet) => println!("あいさつをします!"),
None => println!("あいさつしません!"),
};
println!("{}", greet.unwrap());
}
2: Some(_greet)
fn main() {
let greet = Some(String::from("こんにちは!"));
match greet {
Some(_greet) => println!("あいさつをします!"),
None => println!("あいさつしません!"),
};
println!("{}", greet.unwrap());
}
3: Some(_)
fn main() {
let greet = Some(String::from("こんにちは!"));
match greet {
Some(_) => println!("あいさつをします!"),
None => println!("あいさつしません!"),
};
println!("{}", greet.unwrap());
}
正解発表
正解は3でした!
各コードを実行した結果は以下のようになりました。
パターン1について
$ cargo run
Compiling scrap v0.1.0
warning: unused variable: `greet`
--> src/main.rs:5:14
|
5 | Some(greet) => println!("あいさつをします!"),
| ^^^^^ help: if this is intentional, prefix it with an underscore: `_greet`
|
= note: `#[warn(unused_variables)]` on by default
error[E0382]: use of partially moved value: `greet`
--> src/main.rs:9:22
|
5 | Some(greet) => println!("あいさつをします!"),
| ----- value partially moved here
...
9 | println!("{}", greet.unwrap());
| ^^^^^ value used here after partial move
|
= note: partial move occurs because value has type `String`, which does not implement the `Copy` trait
help: borrow this binding in the pattern to avoid moving the value
|
5 | Some(ref greet) => println!("あいさつをします!"),
| +++
For more information about this error, try `rustc --explain E0382`.
warning: `scrap` (bin "scrap") generated 1 warning
error: could not compile `scrap` (bin "scrap") due to 1 previous error; 1 warning emitted
所有権が移動した後に変数greetを使用しようとするため、エラーになってしまいました。
Rustコンパイラは所有権を移動させない方法として、refを付けることを提案してくれていますね!
また、greetという変数を使用していないという警告が出ていますね!
パターン2について
❯ cargo run
Compiling scrap v0.1.0
error[E0382]: use of partially moved value: `greet`
--> src/main.rs:9:22
|
5 | Some(_greet) => println!("あいさつをします!"),
| ------ value partially moved here
...
9 | println!("{}", greet.unwrap());
| ^^^^^ value used here after partial move
|
= note: partial move occurs because value has type `String`, which does not implement the `Copy` trait
help: borrow this binding in the pattern to avoid moving the value
|
5 | Some(ref _greet) => println!("あいさつをします!"),
| +++
For more information about this error, try `rustc --explain E0382`.
error: could not compile `scrap` (bin "scrap") due to 1 previous error
こちらもまた、所有権が移動した後に変数greetを使用しようとするため、エラーになってしまいました。
しかし、今回はgreetを使用していないという警告は出ていませんね!
パターン3について
$ cargo run
Compiling scrap v0.1.0
Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.41s
Running `target/debug/scrap`
あいさつをします!
こんにちは!
正常にターミナルに出力することができました!
左辺を_とすると、所有権の移動が発生しないんですね!
まとめ
- 変数として束縛すると所有権が移動する(パターン1・2)
-
_は値を無視するパターンなので所有権も移動しない(パターン3) - 未使用変数を警告なしで保持したい場合は
_variableのように接頭辞_を付ける
参考文献
Discussion