IdeaHat
IdeaHat

Reputation: 7881

Match String Tuple in Rust

This is one of those simple-but-I-don't-know-how-to-do-it-in-rust things.

Simply put:

pub fn pair_matcher(tup: &(String, String)) {
    match tup {
        &("foo".as_string(), "bar".as_string()) => print!("foobar"),
        _ => print!("Unknown"),
    }
}

I get the error

-:3:17: 3:18 error: expected `,`, found `.`
-:3          &("foo".as_string(),"bar".as_string())=> { print!("foobar"); }
                    ^

How do you match this?

Upvotes: 3

Views: 4252

Answers (2)

Chris Morgan
Chris Morgan

Reputation: 90742

The left hand side of each branch of a match is not an expression, it is a pattern, which restricts what can go there to basically just literals (plus things like ref which change the binding behaviour); function calls are right out. Given how String works, it’s not possible to get one of them into a pattern (because you can’t construct one statically). It could be achieved with if statements:

if tup == ("foo".to_string(), "bar".to_string()) {
    print!("foobar")
} else {
    print!("Unknown")
}

… or by taking a slice of the Strings, yielding the type &str which can be constructed literally:

match (tup.0.as_slice(), tup.1.as_slice()) {
    ("foo", "bar") => print!("foobar"),
    _ => print!("Unknown"),
}

Constructing a new String each time is an expensive way of doing things, while using the slices is pretty much free, entailing no allocations.

Note that the .0 and .1 requires #![feature(tuple_indexing)] on the crate; one can do without it thus:

 let (ref a, ref b) = tup;
 match (a.as_slice(), b.as_slice()) {
     ("foo", "bar") => print!("foobar"),
     _ => print!("Unknown"),
 }

Because, you see, the left hand side of a let statement is a pattern as well, and so you can pull the tuple apart with it, taking references to each element, with (ref a, ref b) yielding variables a and b both of type &String.

The Patterns section of the guide goes into some more detail on the subject.

Upvotes: 4

IdeaHat
IdeaHat

Reputation: 7881

The solution here is that you need to cast types in the other direction:

match (tup.0.as_slice(), tup.1.as_slice()) {
    ("foo", "bar") => print!("foobar"),
}

Upvotes: 1

Related Questions