Rust lang series episode #14—matching (#rust-series)

in #rust-series8 years ago (edited)

In previous episode of this series we discussed conditions (among the others). Today we will discuss more powerful ways for conditions and pattern matching that is provided by match statement in Rust.

Why matching?

Why not to use if conditions? Why do we need matching? There are multiple reasons. Two most important reasons are:

  • matching is more powerful
  • matching is more comfortable

But it's true, for many things we can use if/else-if/else statements

let answer = "Steemit";
if (answer == "Facebook") {
  println!("The answer is Facebook");
} else if (answer == "Reddit ") {
  println!("The answer is Reddit");
} else {
  println!("The answer is something unexpected: {}", answer);
}

# output
The answer is something unexpected: Steemit

In many languages there is switch statement which is allowing us to do the same even more efficiently.

switch (this will not work in Rust)

Check this java code

String answer = "Steemit";
switch (answer) {
    case "Facebook": System.out.print("The answer is Facebook"); break;
    case "Reddit": System.out.print("The answer is Reddit"); break;
    default: System.out.print("The answer is something unexpected: " + answer);
}

match

Rust doesn’t switch but much better match wi with patterns

let answer = "Steemit";
match answer {
  "Facebook" => println!("The answer is Facebook"),
  "Reddit" => println!("The answer is Reddit"),
  _ => println!("The answer is unexpected: {}", answer),
}

# output
The answer is unexpected: Steemit

Underscore char

Underscore char "_" in Rust says something like “whatever” or “I don’t care”. In match expression it says “all other values”.

Patterns

We can match multiple patterns in a single statement with using "|" and we can also define ranges with using "..."

let result = 2;
match result {
  1 | 2 => println!("result is one or two"),
  3...10 => println!("result is greater than 2 but max 10"),
  _ => println!("result is not one or two"),
}

# output
result is one or two

Destructuring

We can also get sub-values of struct or enum easily by using destructuring. When we want just some first member(s) we can avoid specifying the rest with "..".

struct Article {
    id: i32,
    upvotes: i32,
}

let point = Article { id: 1, upvotes: 0 };

match point {
    Article{ id , .. } => println!("Article ID: {}", id),
}

# output
Article ID: 1

Speaking about destructuring we should also mention tuples which were slightly touched before. Remembering tuples? We spoke about them in the episode dedicated to functions. Imagine we have a function that returns multiple article metrics as tuple but we need just first and third of them for further processing. We can destructure them like this and avoid second one with using "_".

fn get_article_metrics_fake(id: i32) -> (i32, i32, i32) {
    (1, 50, 26)
}

fn main() {
    let (_, upvotes, comments) = get_article_metrics_fake(1);
    println!("upvotes: {}", upvotes);
    println!("comments: {}", comments);
}

# output
upvotes: 50
comments: 26

Ignored binding

We can also easily ignore type and value of variant if we don't need it .

let result : Result<i32,i32> = Result::Ok(1);

match result {
    Ok(value) => println!("Result value: {}", value),
    Err(_) => println!("Error!"),
}

# output
Result value: 1

What we can match?

We can somehow match basically Rust types.

Postfix

That's all for today, thank you for your appreciations, feel free to comment and point out possible mistakes (first 24 hours works the best but any time is fine). Jesus bless your programming skills, use them wisely and see you next time.

Meanwhile you can also check official documentation to find more about discussed topics:

#rust-series
#rust-lang
#rust

Coin Marketplace

STEEM 0.25
TRX 0.20
JST 0.038
BTC 96375.67
ETH 3572.25
USDT 1.00
SBD 3.77