'How do I match based on a dynamic variable?

Is it possible to match on a dynamic variable instead of only literals?

In this code, the first match should do the same as the commented out match (number[0] being 0 and number[1] being 1):

const NUMBERS: [i8; 2] = [0, 1];

fn test() {
    let current = 5;

    let string = match current % 2 {
        NUMBERS[0] => "even", // This does not work
        NUMBERS[1] => "odd",  // This does not work
        _ => unreachable!(),
    };

    // let string = match current % 2 {
    //     0 => "even",
    //     1 => "odd",
    //     _ => unreachable!()
    // };
}


Solution 1:[1]

Despite what the other answers say, it is possible to do what you want, but you need to make an explicitly named constant for each case.

const numbers: [i8; 2] = [
    0, 1
];

fn test() {
    let current = 5;
    
    const NUMBERS0: i8 = numbers[0];
    const NUMBERS1: i8 = numbers[1];

    let string = match current % 2 {
        NUMBERS0 => "even",   // This does not work
        NUMBERS1 => "odd",    // This does not work
        _ => unreachable!()
    };

    // let string = match current % 2 {
    //     0 => "even",
    //     1 => "odd",
    //     _ => unreachable!()
    // };
}

This works only because your expressions are const. Non-const expressions cannot be used in patterns. The intermediary NUMBERS0 and NUMBERS1 constants are necessary for syntax reasons. The left side of => is not an expression but a pattern. Some patterns look like expressions, but not all expressions have a pattern lookalike.

Solution 2:[2]

is it possible in rust to match on a dynamic variable

No. As the name implies, pattern-matching works on the basis of patterns, not expressions or values.

You can see this from the grammar: a MatchArm is OuterAttribute* Pattern MatchArmGuard?, and a pattern is an enumerated set of specific constructs. Mostly literals, identifiers, paths, and ways to combine those (structs, tuples, slice, ... patterns).

Solution 3:[3]

First calculate the value then pass to match

const numbers: [i8; 2] = [0, 1];
let current = 5;

let string = match numbers[current % 2] {
    0 => "even",
    1 => "odd",   
    _ => unreachable!()
};
println!("{}",string);

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 mcarton
Solution 2 Masklinn
Solution 3 SUDHIR KUMAR