Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Idiomatic way to use a computed value as a pattern in match

Tags:

rust

What is the best way to use a value computed at runtime as one of the patterns in a match?

I have a value (byte) that I need to match against other values. Some of the values are fixed (b'0'..b'9'). Others are computed at runtime (c = some_function()).

My current solution is to use a fake variable and a if guard (i.e. k if (k == c)), but it does not look very nice to me. I tried using just c but that gets interpreted as a catch-all variable, rather than substituted for the value of c in that context.

The following code snippet shows the problem: (also on playpen)

fn main() {
    fun(b'5', 0);
    fun(b'C', 0);
    fun(b'C', 2);
}

fn fun(byte: u8, i: uint) {
    let CHARS = b"ABCDEFGH";
    let c = CHARS[i];

    let msg = match byte {
        b'0'..b'9' => "numeric",
        // c => "same char", // <-- I would had preferred this
        k if (k == c) => "same char",
        _ => "different char",
    };

    println!("fun({}, {} [{}]) = {}", byte, i, c, msg);
}

Is this the most idiomatic construct that Rust can offer?

like image 447
gioele Avatar asked Aug 18 '14 14:08

gioele


1 Answers

In short, yes, you should use pattern guards for this.

To make it possible there should be a way to differentiate plain bindings and equality checks. Scala, for example, does this based on variable case: if it starts with capital letter, it is an equality check; otherwise it is a pattern binding. There is no such mechanism in Rust, so no, it is impossible now.

like image 157
Vladimir Matveev Avatar answered Nov 16 '22 01:11

Vladimir Matveev