rustのユニットについて理解する

rust

ユニットをひとことで

「特に何もない」を表現する記号

ユニットを返す関数

ユニットを返す関数を書いてみます。

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

ユニット様構造体はトレイト実装専用の構造体

値が一つしかないなら、何に使うの?と思いますが、ユニット様構造体は構造体なのでトレイト実装ができます。つまり、「値は保持しなくていいけど、トレイト実装はしたい」時に使うようです。

最後に

今まで何気なく使っていたユニットですが、実は型や値としての使い方があるということに気づきました。ユニットは度々出てくるので、改めて理解できてよかったです。

コメント

タイトルとURLをコピーしました