Enums and match
Enums carry payloads; match compiles to an if-chain
A payload enum is a tagged table with a constructor per variant and a union type the analyzer can narrow. A unit enum is a string literal union, so it serializes for free.
Alloyenums.aly
1enum Msg 2 Join(Player) 3 Chat(Player, string) 4end 5local who = match msg with 6 case Join(p) then p.Name 7 case Chat(p, text) then `{p.Name}: {text}` 8end
Emitted Luausame line count
1local __alloy = require("@alloy") local Msg = {} Msg.__index = Msg 2function Msg.Join(_1: Player): typeof(setmetatable({} :: { tag: "Join", _1: Player }, Msg)) return (setmetatable({ tag = "Join", _1 = _1 }, Msg) :: any) end 3 function Msg.Chat(_1: Player, _2: string): typeof(setmetatable({} :: { tag: "Chat", _1: Player, _2: string }, Msg)) return (setmetatable({ tag = "Chat", _1 = _1, _2 = _2 }, Msg) :: any) end 4function Msg.is(v) return (type(v) == "table" and getmetatable(v) == Msg) end Msg.__tostring = function(v) return __alloy.show_variant("Msg", v) end type Msg = typeof(setmetatable({} :: { tag: "Join", _1: Player }, Msg)) | typeof(setmetatable({} :: { tag: "Chat", _1: Player, _2: string }, Msg)) 5local who = ( 6 if type(msg) == "table" and msg.tag == "Join" then msg._1.Name 7 elseif type(msg) == "table" and msg.tag == "Chat" then `{msg._1.Name}: {msg._2}` else error("match: no arm covers this value", 2) 8) return nil
- Patterns nest: or-patterns, struct patterns, table and array patterns, literals, guards with
and, anddefault. - A pattern binds outside a match:
local Join(p) = msgreads one variant's payload and raises on another;local Join(p) = msg else return endleaves instead, andif local Join(p) = msg thentests it. matchis a statement or an expression; the expression form parenthesizes so it drops into any position.impl Msgadds methods to an enum the way it does to a struct.- Hover on a variant shows
Msg.Chat(Player, string)even inside a pattern, where the emit has only a string.
