#Weird behavior in match statements

45 messages · Page 1 of 1 (latest)

safe salmon
#

Somehow variable names in match statements just don't work. (those match statements that have an or condition)

    let i = 2;

    // this works perfectly fine
    match i {
        0 | 5  => println!("First or last index"),
        _ => println!("Somewhere in the middle")
    };

    // but this doesn't?
    let first = 0;
    let last = 5;
    match i {
        last | first => println!("First or last index"),
        _ => println!("Somewhere in the middle")
    };

I think the code explains my confusion well enough. I can't tell why having variable names suddenly makes rust complain. If you also wanna know the full error complaints check the image.

timid zephyr
#

This is expected behavior. match statements take in some expression, and then pattern match against the value and type of the input.

When you say last | first =>, the code in-front of the => must be a pattern, not a variable to some data.

safe salmon
#

but why is comparing against a simple variable fine then

    match i {
        last => println!("hi"),
        _ => println!("bye")
    }

this code works

timid zephyr
#

That isn't comparing against a variable.

#

last => binds the value of the matched i, for use inside the match arm.

#

_ => in this case, will never be reached.

safe salmon
#

oh yeah you're right that actually doesn't work

timid zephyr
#

?play

let i = 5;
let last = 25;
match i {
    last => println!("{last}"),
    _ => println!("other"),
}
hollow stratusBOT
#
5```
safe salmon
#

I think I see it now kinda

#

it checks if i is any kind of number, it succeeded, so now it takes that number (called "last") and forwards it to the println

timid zephyr
#

Right.

#

last in this case, is an example of an "IdentifierPattern". Where, the pattern will successfully match any value, and then bind that value to the given identifier, for use inside the branch.

safe salmon
#

got it

timid zephyr
#

_ is the exact same, except it doesn't bind the value to anything.

safe salmon
#

yeah that makes sense

#

in that case

#

i if i == (first | last) something like this should be used instead

#

but idk if that's more readable than just having 2 arms

#

one with 0

#

one with list.len() - 1

timid zephyr
#

ehh well you can't exactly do just list.len() - 1 =>. You'd have to do _ if list.len() - 1 =>.

#

In which case, you might as well just use a regular if statement.

safe salmon
#

hmm

#

yeah ig I'll just do that

#

thanks for the explanation

timid zephyr
#

The issue is that list.len() - 1 is an expression, not a pattern.

safe salmon
#

I'll read through that

pine wraith
#

You can use constants in this position:

    const FIRST: usize = 0;
    const LAST: usize = 5;
    match i {
        LAST | FIRST => println!("First or last index"),
safe salmon
#

that's cool

#

sadly my list isn't constant length

safe salmon
#

btw can the difference between if/else and match be understood as a difference in how they prefer to compare things? like if/else cares more about exact equality, but match more-so "structural" equality?

pine wraith
#

if doesn't compare anything at all; it receives a bool and branches based on that alone

floral eagle
#

Structural equality is a great way to put it, yes

#

match cares about the "shape" of the data

pine wraith
#

(or you could say that if is a match ... { true => , false => })

safe salmon
safe salmon
#

a map between if/else and match

#

category theory intensifies

pine wraith
#

most Rust control flow can be turned into match and loop

floral eagle
#

In fact, the compiler used to do that for simplicity, before we changed it for better error messages

safe salmon
#

that's a neat curiosity lol