【问题标题】:How do I "toggle" through enum variants?如何通过枚举变体“切换”?
【发布时间】:2014-11-10 03:36:10
【问题描述】:

我想编写一个函数,将提供的值切换/切换到枚举中的下一个值并在末尾环绕:

enum Direction { NORTH, SOUTH, EAST, WEST }

例如,NORTH => SOUTHSOUTH => EASTEAST => WESTWEST => NORTH

有没有比In Rust, is there a way to iterate through the values of an enum? 中描述的手动创建静态数组更简单的方法

use Direction::*;
static DIRECTIONS: [Direction; 4] = [NORTH, SOUTH, EAST, WEST];

枚举不应该被“枚举”吗?我依稀记得以前在 Rust 中看到过一个例子,但我似乎找不到它。由于 Rust 枚举更像联合/变体,我想这会使事情复杂化。

【问题讨论】:

标签: rust


【解决方案1】:

Vladimir 的回答是正确的,但程序员必须记住在向enum 添加新成员时更改幻数“4”。 turn 的这个定义应该更容易维护:

#[derive(Debug, Copy, Clone, FromPrimitive)]
enum Direction {
    NORTH = 0,
    SOUTH,
    EAST,
    WEST,
}

fn turn(d: Direction) -> Direction {
    match FromPrimitive::from_u8(d as u8 + 1) {
        Some(d2) => d2,
        None => FromPrimitive::from_u8(0).unwrap(),
    }
}

【讨论】:

  • 我喜欢你的解决方案!您的解决方案可以说更难以改变(有点冗长,但仍然很容易推理)。谢谢!
【解决方案2】:

我想这样的事情可以解决问题:

#[macro_use]
extern crate num_derive;
extern crate num_traits;

use num_traits::FromPrimitive;

#[derive(Debug, Copy, Clone, FromPrimitive)]
enum Direction {
    NORTH = 0,
    SOUTH,
    EAST,
    WEST,
}

fn turn(d: Direction) -> Direction {
    FromPrimitive::from_u8((d as u8 + 1) % 4).unwrap()
}

fn main() {
    use Direction::*;
    for &d in [NORTH, SOUTH, EAST, WEST].iter() {
        println!("{:?} -> {:?}", d, turn(d));
    }
}

这不需要unsafe,因为它使用自动派生的FromPrimitive trait。

【讨论】:

  • 我希望有一种安全的方法(这就是为什么我写了评论而不是提出不安全的转换作为答案),但是您的方法仍然依赖于创建一个包含所有枚举变体的数组, OP 提到这是他已经意识到的可能性
  • @PaoloFalabella,你是什么意思,它需要创建一个数组?它没有;数组只是为了说明这一点。主要工作在turn() 函数中完成,该函数安全且不使用数组。
【解决方案3】:

我更愿意通过match 语句显式编码下一个方向:

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

impl Direction {
    fn turn(&self) -> Self {
        use Direction::*;
        match *self {
            North => South,
            South => East,
            East => West,
            West => North,
        }
    }
}

fn main() {
    use Direction::*;

    for i in &[North, South, East, West] {
        println!("{:?} -> {:?}", i, i.turn());
    }
}

【讨论】:

  • 在这里很好地使用了use。谢谢。
猜你喜欢
  • 1970-01-01
  • 2020-08-09
  • 1970-01-01
  • 1970-01-01
  • 2021-10-31
  • 1970-01-01
  • 2011-10-28
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多