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
matchis 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.