Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I "toggle" through enum variants?

Tags:

rust

I'd like to write a function which toggles/switches the provided value to the next in the enum and wraps around at the end:

enum Direction { NORTH, SOUTH, EAST, WEST }

For example, NORTH => SOUTH, SOUTH => EAST, EAST => WEST, WEST => NORTH.

Is there an easier way than manually creating a static array as described in In Rust, is there a way to iterate through the values of an enum?

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

Aren't enums suppose to be "enumerated"? I vaguely remember seeing an example before in Rust, but I can't seem to find it. Since Rust enums are more like unions/variants, I guess this complicates things.

like image 235
Jacob Wang Avatar asked Sep 16 '14 11:09

Jacob Wang


Video Answer


2 Answers

I would prefer to explicitly encode the next direction via a match statement:

#[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());
    }
}
like image 136
Shepmaster Avatar answered Sep 18 '22 21:09

Shepmaster


Vladimir's answer is correct but the programmer must remember to change the magic number "4" when adding a new member to the enum. This definition for turn should be easier to maintain:

#[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(),
    }
}
like image 21
gfour Avatar answered Sep 20 '22 21:09

gfour