ユニットをひとことで
「特に何もない」を表現する記号
ユニットを返す関数
ユニットを返す関数を書いてみます。
fn hello() -> () {
println!("hello");
}
fn main() {
hello();
}
$ cargo run
hello
hello関数の戻り値にユニットを指定します。つまり、戻り値は特に何もないということです。
お気づきかもしれませんが、実は戻り値のユニットは省略可能です。rustのlinterのclippyによれば、省略推奨のようです。
戻り値を省略してみると、見慣れた形の関数になりました。つまり、戻り値なしの関数はユニットを返しているということですね!
fn hello() {
println!("hello");
}
fn main() {
hello();
}
$ cargo run
hello
ユニットは型でもあり値でもある
関数が戻り値をユニットにしたときは、ユニットを値として扱いました。実はユニットは型としても使えます。以下は型としてユニットを使用している例です。コンパイルも通るので合法です。
let mut a:Vec<()> = vec![];
a.push(());
こんなこともできます。
let a: () = ();
ユニットの使い方から、ユニットの性質が見えてきます。
ユニット型は唯一の値として、ユニットを持つ
ユニット型には、ユニットのみを代入できます。例えば上記の例で、ユニット型に数値を代入しようとしてみると、エラーになります。エラーメッセージを見ると、値としてユニットが期待されていることが分かります。
let mut a:Vec<()> = vec![];
a.push(10); // <- expected (), found integer
あたかもユニットの性質を導き出したかのように書きましたが、ドキュメントに書いてあります笑。
unit - Rust
The `()` type, also called “unit”.
ユニット様構造体
ユニットのように、唯一の(特に意味を持たない)値を持つ構造体をユニット様構造体と言います。ユニット様構造体は、フィールドを持たない構造体として定義されます。
#[derive(Debug)]
struct Hoge;
以下のように、Hoge構造体の値はHogeしか許されません。
let a = Hoge;
eprintln!("a = {:?}", a);
$ cargo run
hoge = Hoge
ユニット様構造体はトレイト実装専用の構造体
値が一つしかないなら、何に使うの?と思いますが、ユニット様構造体は構造体なのでトレイト実装ができます。つまり、「値は保持しなくていいけど、トレイト実装はしたい」時に使うようです。
最後に
今まで何気なく使っていたユニットですが、実は型や値としての使い方があるということに気づきました。ユニットは度々出てくるので、改めて理解できてよかったです。
コメント