Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How is match implemented in a language like Rust?

I'm not a functional programmer. So I'm not very familiar with pattern matching, patterns, or any of that stuff. To me I only understand the concept of the good old switch statement.

How would a compiler implement a match statement? What exactly is the difference between match and a switch? There's a GNU C99 extension that allows you to have ranges in cases of a switch, is there a difference between:

match x {
    0 ... 9 => ...,
    _ => ...,
}

and

switch (x) {
case 0 ... 9: ...; break;
default: ...; break;
}

Note that the second snippet is a simple C switch with this GNU extension.

like image 926
Jon Flow Avatar asked Apr 28 '16 16:04

Jon Flow


People also ask

How does match work in Rust?

Rust has an extremely powerful control flow construct called match that allows you to compare a value against a series of patterns and then execute code based on which pattern matches.

How do you match types in Rust?

Instead of matching on an element, call the method in the trait on it. TLDR: in Rust, to match over type, we create a trait, implement a function for each type and call it on the element to match. Surround it with backticks to mark it as code. Single backticks for inline code, triple backticks for code blocks.

What is pattern matching in Swift?

In Swift, there are two basic kinds of patterns: those that successfully match any kind of value, and those that may fail to match a specified value at runtime. The first kind of pattern is used for destructuring values in simple variable, constant, and optional bindings.


Video Answer


1 Answers

A pattern match on constant values can be implemented as a jump table or a sequence of conditional jumps - just like switch statements. Allowing ranges does not change this situation much.

Rust enums (at least the ones with members) are implemented like tagged unions, i.e. structs that contain a tag and a union of structs that contain the members.

A pattern match on an enum is then simply translated as a switch on its tag (binding the variables bound by the pattern to the members of the union). So something like this Rust code:

enum Result {
  SingleResult(i32),
  TwoResults(i32, i32),
  Error
}

match someResult {
  Result::SingleResult(res) => f(res),
  Result::TwoResults(res1, res2) => g(res1, res2),
  Result::Error => error()
}

would translate to the same machine code (presumably) as the following C code:

struct Result {
  enum {
    SingleResult, TwoResults, Error
  } tag;
  union {
    struct {
      int arg1;
    } singleResult;
    struct {
      int arg1;
      int arg2;
    } twoResults;
  } value;
};

switch(someResult.tag) {
  case SingleResult: {
    int res = someResult.value.singleResult.arg1;
    f(res);
    break;
  }
  case TwoResults: {
    int res1 = someResult.value.twoResults.arg1;
    int res2 = someResult.value.twoResults.arg2;
    g(res1, res2);
    break;
  }
  case Error: {
    error();
    break;
  }
}
like image 130
sepp2k Avatar answered Nov 15 '22 10:11

sepp2k