web-dev-qa-db-ja.com

Rustで、列挙型の値を反復処理する方法はありますか?

私はJavaバックグラウンドから来ており、enum Direction { NORTH, SOUTH, EAST, WEST}そして、次のように拡張されたforループを使用して、各値を順番に処理できます。

for(Direction dir : Direction.values())  {
    //do something with dir
}

Rust enums。

53
dougli1sqrd

いいえ、ありません。 Rustの列挙型はJavaの列挙型よりもはるかに強力です-実際には本格的な 代数データです) types 。たとえば、この列挙型の値を反復することをどのように期待しますか?

enum Option<T> {
    None,
    Some(T)
}

2番目のメンバーSomeは静的定数ではありません。これを使用してOption<T>の値を作成します。

let x = Some(1);
let y = Some("abc");

したがって、any列挙型の値を反復処理することができる正気な方法はありません。

もちろん、static列挙型(つまり、静的項目のみの列挙型)の特別なサポートをコンパイラに追加することは可能だと思うので、 enumの値またはそれらを使用した静的ベクトルを返す関数を生成しますが、コンパイラーをさらに複雑にしてもそれだけの価値はないと私は信じています。

この機能が本当に必要な場合は、カスタム構文拡張機能を記述できます( this の問題を参照)。この拡張機能は、識別子のリストを受け取り、これらの識別子をコンテンツとして持つenumおよび静的定数ベクトルを出力する必要があります。通常のマクロもある程度は機能しますが、私が覚えている限り、多重度でマクロ引数を2回転写することはできないため、列挙型要素を手動で2回記述する必要があり、不便です。

また、この問題は興味深いかもしれません: #5417

そしてもちろん、いつでも列挙型要素のリストを手動で返すコードを書くことができます。

25

列挙型が(例のように)Cに似ている場合、これを行うことができます:

use self::Direction::*;
use std::slice::Iter;

#[derive(Debug)]
pub enum Direction { North, South, East, West }

impl Direction {
    pub fn iterator() -> Iter<'static, Direction> {
        static DIRECTIONS: [Direction;  4] = [North, South, East, West];
        DIRECTIONS.into_iter()
    }
}


fn main() {
    for dir in Direction::iterator() {
        println!("{:?}", dir);
    }
}
27
A.B.

Strum クレートを使用して、列挙型の値を簡単に反復できるようになりました。

extern crate strum;
#[macro_use] extern crate strum_macros;

use strum::IntoEnumIterator;

#[derive(Display, EnumIter)]
enum Direction
{
    NORTH,
    SOUTH,
    EAST,
    WEST
}

fn main()
{
    for direction in Direction::iter()
    {
        println!("{}", direction);
    }
}

出力:

NORTH
SOUTH
EAST
WEST
9
Jordan Mack

crate plain_enum

次のようにCのような列挙型を宣言するために使用できます。

#[macro_use]
extern crate plain_enum;

plain_enum_mod!(module_for_enum, EnumName {
    EnumVal1,
    EnumVal2,
    EnumVal3,
});

そして、次のようなことができるようになります:

for value in EnumName::values() {
    // do things with value
}

let enummap = EnumName::map_from_fn(|value| {
    convert_enum_value_to_mapped_value(value)
})
8
phimuemue