lloyAlloy on GitHub
match
Docs

match

Updated
match expr as name with
    case Pat then ...
    default ...
end

Pattern match, as a statement or an expression; match a, b with matches several values at once, each arm with as many patterns.

as name is optional and names the value under match. The name is in scope in every case body, every guard, and default, and it reads the value the arm narrowed. The head computes the value once, so match f() as x with calls f one time. Each value of a multi-value head takes its own name, match a as left, b as right with. A pattern that binds the alias is an error.

The patterns: a variant with its payload, Ok(v), Move(x, y); a bare name or _ for anything (a binding starts lowercase or with _; a bare name with a capital is a unit variant, so one that no enum in scope has is an error, and case MAX with MAX in scope is one too: compare it in a guard); a literal, 1, "a", true, nil, -1; a dotted path, Color.Red; a struct, Vec2 { x = 0, y }, where y alone binds the field; an array, [first, ...rest], with ...rest for the tail. or joins alternatives, where expr is a guard, case n where n > 5, the word a for filter takes (the older and expr still reads, and match_guard_and rewrites it), and if local Pat = e and local Pat = e else ... end use the same patterns outside a match. An exhaustive match needs no default. default comes last: a case after it is an error.

An arm can run statements before its value. The last line of the arm is the value, as in a Rust block:

local score = math.random(0, 3)
local label = match score with
    case 0 then "none"
    default
        print(score)
        tostring(score)
end

A match with such an arm stands after local x =, x =, or return. The arms move into that statement, so no line moves. return in an arm leaves the function around the match, and break and continue go to the loop around it. An arm that ends in a different statement is an error. A line that starts with (, [, {, -, or a string does not join the line above, so -y there is the value.

Emits an if-chain on the tag.

The word is also free as a name. match before a scrutinee is the keyword; match(s, p), match = f, and match.field read the Luau way, so a local named match may hold string.match. A bracket reads both ways and the with decides: match [k] with matches an array, match[k] = 1 indexes a table.