Have you ever looked for a way to pattern-match a certain type or value and wished you could extract additional data from each match (or case)? In C you can use unions for this, F# has discriminated unions and in C# you can use inheritance and reflection to achieve this. This post shows an example how to use enums with additional data and how to use them with pattern matching.

Pattern-matching tagged unions in Rust.

Rustlang supports enums that look like this:

enum Endpoint {
  IP,
  IPAndPort
}

The enum has two values and it looks like one of them would indicate an IP-address and the other one an IP-address and port. In Rust you can actually store that data together with the enum like this:

enum Endpoint {
  IP(String),
  IPAndPort(String, i32)
}

Pattern matching in Rust

You can use the enum to create a variable and pattern-match on it like this:

e = Endpoint::IP(String::from("127.0.0.1"));

match e {
  Endpoint::IP(ip) => println!("Connecting to {} at default port", ip),
  Endpoint::IPAndPort(ip, port) => println!("Connecting to {}:{}", ip, port),
}

Complete example

enum Endpoint {
  IP(String),
  IPAndPort(String, i32)
}

fn match_address(endpoint: Endpoint) {
  match endpoint {
    Endpoint::IP(ip) => println!("Connecting to {} at default port", ip),
    Endpoint::IPAndPort(ip, port) => println!("Connecting to {}:{}", ip, port),
  }
}

fn main() {
  match_address(Endpoint::IP(String::from("127.0.0.1")));
  match_address(Endpoint::IPAndPort(String::from("127.0.0.1"), i32::from(8082)));
}

Output:

Connecting to 127.0.0.1 at default port
Connecting to 127.0.0.1:8082

For more info about tagged unions and its history, read this great article by Pat Shaughnessy

Written by Loek van den Ouweland on 2018-09-19.
Questions regarding this artice? You can send them to the address below.