Patterns can match exact values, ranges, choice variants or option shapes.
if status is:
Ready => io.line("ready")
Waiting => io.line("waiting")
;
A choice match does not need else => when every variant is covered.
Payload variants expose their fields through captures:
if response is:
Success => io.line("done")
Err(message) => io.line(message)
;
The capture name must match the field name.
Use as when the local name should be different:
Err(message as error_text) => io.line(error_text)
Options have two complete shapes: absent and present.
if maybe_name is:
none => io.line("missing")
|name| => io.line(name)
;
Most other value matches need else => because the compiler cannot list every possible Int, String or other scalar value.
Match patterns describe the values an arm accepts.
Literal patterns
A literal pattern must be compatible with the scrutinee type.
if value is:
1 => io.line("one")
2 => io.line("two")
3 => io.line("three")
else =>
;
One statically typed match can't mix unrelated Int, String and Bool literal patterns.
Choice variants
if status is:
Ready => io.line("ready")
Status::Waiting => io.line("waiting")
;
Choice payload captures
if response is:
Success => io.line("done")
Err(message) => io.line(message)
Pending(retry_count, message as pending_message) =>
io.line(pending_message)
;
Option patterns
Options support:
none- literal present-value patterns
- relational present-value patterns
|name| to capture any present value
An option match may omit else => only when it has both:
- an unguarded
none arm - an unguarded
|name| present-value capture
if maybe_name is:
none => io.line("missing")
|name| => io.line(name)
;
Literal or relational option arms don't replace the unguarded present-value capture when else => is omitted.
Relational patterns
< value
<= value
> value
>= value
Relational patterns support Int, Float and Char.
The catch-all arm
else => is the only full-match catch-all. A bare unknown name in choice pattern position is treated as an unknown or invalid variant. A bare name in other full-match pattern positions is invalid syntax.
if value is:
0 => io.line("zero")
else => io.line("other")
;
Implementation gap
The accepted language removes general bare-name capture from every full-match position and removes String from relational pattern subjects. The current compiler still accepts some of these removed forms. Stage B of the language documentation plan removes the obsolete parser and analysis paths. See Progress for the recorded drift.
Choice payload capture contract
- Payload captures must list every declared field.
- Captures stay in declaration order.
- The source name before
as must exactly match the declared field name. as local_name changes only the arm-local binding.- Duplicate local bindings are invalid.
- Wildcard payload captures aren't supported.
- Named assignment syntax such as
Err(message = text) isn't payload-pattern syntax. - Nested payload patterns are deferred.
Exhaustiveness
- An ordinary non-choice full match requires
else =>. - An option match may instead use unguarded
none plus unguarded |name|. - A choice match may omit
else => only when every variant is covered. - Any guarded choice arm requires
else =>. - The same choice variant can't be matched more than once.
- Payload exhaustiveness is tag-level. One valid payload capture arm covers every value of that variant.
- A statement match may use bodyless
else =>. - A value-producing match must produce the required values on every selected path.