Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Match

match is Flint’s multi-branch pattern dispatch construct and one of the most powerful tools in the language. It replaces switch, unwraps Option and Result, destructures enums and structs, binds inner values, and guards branches with conditions, all in one place. There is no switch; match is the whole story. It earns its own chapter. Learn it well and you will use it constantly.

match token {
    Token.Ident { text } => return Ok(text)
    Token.Number { value } => return Ok(str.from_int(value))
    Token.Eof => return Err(ParseError.unexpected_eof)
    _ => return Err(ParseError.unexpected_token)
}

Rules

  • match is exhaustive. Every possible variant must be covered.
  • Arms are evaluated top to bottom.
  • The first matching arm wins.
  • _ is the wildcard catch-all.

Patterns

Literal patterns:

match code {
    200 => process_ok(body)
    404 => log.warn("not found")
    500 => log.error("server error")
    _   => log.info("unknown")
}

Enum variant patterns:

match event {
    Event.ButtonPress => handle_press()
    Event.ButtonRelease => handle_release()
    Event.Timeout => handle_timeout()
}

Named-field payload binding:

match token {
    Token.Ident { text } => use_ident(text)
    Token.Error { message, line } => report(message, line)
    Token.Eof => return
}

Positional payload binding:

match message {
    Message.Data(kind, len) => process(kind, len)
    Message.Ready => start()
}

Wildcard payload (_):

match result {
    Ok(_)  => log.info("ok")
    Err(e) => log.error(e)
}

Guards

Arms can have a when guard for additional conditions:

match rising {
    true when level >= BRIGHT_MAX => {
        level = BRIGHT_MAX
        rising = false
    }
    true => level += BRIGHT_STEP
    false when level <= BRIGHT_STEP => {
        level = 0
        rising = true
    }
    _ => level -= BRIGHT_STEP
}

The guard runs only after the pattern matches. A guarded arm does not count toward exhaustiveness; you must still cover the unguarded case.

match as an Expression

When every arm produces a value of the same type, match can be used as an expression:

let next_rising = match rising {
    true when level >= BRIGHT_TURN => false
    _ => rising
}

if let as a Lightweight Alternative

When you only care about one pattern, if let is often cleaner than match:

// Prefer this for simple single-branch cases
if let Some(port) = config.port {
    open(port)
}

// Over this
match config.port {
    Some(port) => open(port)
    None => ()
}

If you only need a presence check and do not need port itself, use config.port.is_some() or config.port.is_none() instead.

What Is Not Supported

  • Nested destructuring (Point { x: 0, y } patterns inside other patterns)
  • Range patterns (1..=10 =>)
  • Tuple patterns
  • Or patterns (A | B =>)

These may be added in future versions.