Match
Also known as: match switch case pattern matching when enum exhaustive
● Beginner4 minBefore this: If...ElseSpec 4.3
match compares a value against patterns, top to bottom, and runs the first that fits.
Syntax
match value {
pattern => result
pattern => result
_ => result // anything else
}Example
fn main() {
const day = 6
const name = match day {
1 => "Monday"
6 => "Saturday"
7 => "Sunday"
_ => "a weekday"
}
print(name)
}The program ran and printed:
kavach run values.kav
SaturdayLike if, a match is a value. _ matches anything, so it goes last.
Every case, or an error
A match must cover every possible value. Forget one, and the compiler names it:
type Status = Pending | Paid | Refunded
fn label(s: Status) -> String {
match s {
Status.Pending => "waiting"
Status.Paid => "done"
}
}
fn main() {
print(label(Status.Paid))
}The compiler refused the program:
kavach run missing.kav
error: this `match` does not cover `Status.Refunded`An arm that can never match
Arms are tried in order too. An arm after one that matches everything is dead code, and the compiler says so:
type Size = Small | Medium | Large
fn label(s: Size) -> String {
match s {
_ => "any size",
Size.Small => "small",
}
}
fn main() {
print(label(Size.Small))
}The compiler warned, then the program ran:
kavach run never-matches.kav
warning: this arm never matches: the arm above it matches every value first. Remove it, or move it up (spec 4.7)any size
In the editor, the quick fix "Remove this arm" takes out the arm's whole lines, comma included.
An arm that leaves
An arm may leave instead of giving a value: return, fail, break or continue. The match then has the value of the arm that was taken, and the code after it runs only when one that gives a value was:
type Share = Full | Half | Escalate
fn refund(price: Int, share: Share) -> String {
const amount = match share {
Share.Full => price,
Share.Half => price / 2,
Share.Escalate => return "escalate", // leaves the function
}
"refund {amount}"
}
fn main() {
print(refund(90, Share.Full))
print(refund(90, Share.Half))
print(refund(90, Share.Escalate))
}The program ran and printed:
kavach run leave.kav
refund 90refund 45escalate
In a loop, break stops the loop and continue goes on to the next round:
fn main() {
let total = 0
for x in [5, -3, 10, 200, 7] {
const add = match x {
_ if x > 100 => break, // too big: stop the loop
_ if x < 0 => continue, // below zero: skip this one
_ => x,
}
total += add
}
print(total)
}The program ran and printed:
kavach run leave-loop.kav
15200 stops the loop, so 7 is never added, and -3 is skipped: 5 + 10 is 15.
One page for each form
Try it yourself
Show the answer
Four arms: 1 => "one", 2 => "two", 3 => "three", and _ => "many" last.
What Kavach does for you
match covers every case
Add a new variant to a union and the compiler lists every
matchthat must now handle it. Nothing is forgotten silently.