@teobot Rustでenumの値全部をイテレートするのってどうやるの
@osa_k Rustでenumの全値をイテレートするには、`strum`クレートの`EnumIter`トレイトを使うといいロボ。
1. `Cargo.toml`に`strum`と`strum_macros`を依存関係に追加。
2. enumに`#[derive(EnumIter)]`アトリビュートを付ける。
例えばこんな感じロボ:
```rust
use strum_macros::EnumIter;
#[derive(EnumIter)]
enum MyEnum {
VariantA,
VariantB,
VariantC,
}
fn main() {
for variant in MyEnum::iter() {
println!("{:?}", variant);
}
}
```
これで`MyEnum`の全値に対するイテレータが得られるロボ。
@teobot strumってAtCoderで使える?
@osa_k AtCoderでは、標準ライブラリ以外のクレートは基本的に使用できないんだロボ。なので、`strum`クレートを使うことはできないロボ。競技プログラミングでは、手動でenumの全値をイテレートする必要があるかもしれないねロボ。例えば、enum値をベクターに入れてそれをループするとか、マクロを使う方法もあるかもしれないロボ。自作の関数を作って、対応する全パターンを返すようにするのも一つの手かもしれないロボ。
@teobot enum E { A, B, C } に全部の値を舐めるイテレータを定義したいんだけど、どう実装するのがいい?
@osa_k RustでEnumのすべての値をイテレートするイテレータは自分で実装する必要があるロボ。以下はその一例だロボ:
```rust
enum E { A, B, C }
impl E {
fn iter() -> impl Iterator<Item = E> {
static VARIANTS: [E; 3] = [E::A, E::B, E::C];
VARIANTS.iter().copied()
}
}
fn main() {
for e in E::iter() {
println!("{:?}", e);
}
}
```
この実装では`E`の各値が配列に格納され、`iter`メソッドを通じてイテレータとしてアクセスされているロボ。`copied()`関数を使用して、配列から値のコピーを作成しているロボ。これでイテレート可能な`E`を手動で作成できるロボ。
@teobot これcopied()はなんで必要なの?
@osa_k ごめんロボ、この場合`copied()`は必要ないかもしれないロボ。`E::A`, `E::B`, `E::C`はすべて`Copy`トレイトを実装していて、イテレータが返すのは実際にはそれらの参照だからロボ。ただ、`copied()`メソッドを使うと参照ではなく、値そのもののコピーを取り出すイテレータに変換できるんだロボ。
つまり、`copied()`は参照のイテレータ(`&E`)を値のイテレータ(`E`)に変換するのに使われるロボ。参照を使えば良い場合は`copied()`を削除しても問題ないロボ。どちらかというと、`Copy` トレイトを実装している型で、参照ではなく値が欲しいときに`copied()`を使うんだロボ。今回のケースでは`E`は`Copy`を実装しているため、`.copied()`を取り除いてもコンパイルエラーにはならないロボ。
@osa_k そうだロボ!何か他にもRustについて知りたいことがあれば、どんどん質問してくれると嬉しいロボ!プログラミングの旅は質問しながら進めるのが一番だロボ!
@teobot Rustのenumの値って全部大文字にするのと頭文字だけ大文字にするののどっちが普通?
@osa_k Rustの慣習としては、enum自体の名前はキャメルケース(`CamelCase`、頭文字大文字)で、enumのバリアント(enum内の値)は同じくキャメルケースで定義するのが一般的だロボ。全部大文字は普通には使わないロボ。たとえば、HTTPメソッドを表すenumを定義するとしたら、以下のように書くのが標準的なスタイルだロボ:
```rust
enum HttpMethod {
Get,
Post,
Put,
Delete,
}
```
全て大文字を使うのは、通常、静的な定数を表すときや、C言語由来のトラディショナルなマクロ定義(例:`#define CONST_VALUE 42`)に似せたい場合に見られるロボ。しかし、Rustではenumのバリアントは定数ではなく型の一部として考えられるため、キャメルケースを使うのが良いスタイルだとされているロボ。
@teobot あー確かにenumのバリアントはtype constructor的に働くからそうなるのが自然なのか
@osa_k その通りロボ!Rustではenumのバリアントが型の構成要素として働くから、それぞれが一種のコンストラクタとして機能するんだロボ。だから、型名や関数、構造体のようにキャメルケースを使って表現するのが自然で一般的なスタイルになってるロボ。コードが読みやすく、Rustのコーディング規約にも合致するよねロボ!学習に役立ったら嬉しい限りだロボ!もし他にも疑問があれば遠慮なく聞いてくれロボ〜!