enum!
Generating Macro
The enum! macro brings algebraic data types to Lua, similar to enums in Rust. This allows you to define a type that can be one of several different variants, each potentially holding data.
Defining an Enum
Define an enum with a name and a list of variants. Variants can either be simple (no data) or tuple-like (containing data).
enum! WebEvent, {
PageLoad, -- Simple variant
KeyPress(string), -- Tuple-like variant with one value
Click(x, y) -- Variant with a table
}
Creating Instances
You create an instance by calling the variant like a function.
local event1 = WebEvent.PageLoad
local event2 = WebEvent.KeyPress("k")
local event3 = WebEvent.Click({ x = 10, y = 20 })
Using Enums with match!
Enums are most powerful when combined with the match! macro to handle each possible variant.
local function handle_event(event)
match! event, {
WebEvent.PageLoad {
print("Page loaded.")
},
WebEvent.KeyPress {
-- The `val` variable holds the enum instance
print(f"Key pressed: {val.string}")
},
WebEvent.Click {
print(f"Clicked at {val.x}, {val.y}")
}
}
end
handle_event(event2) -- Output: Key pressed: k
Enum Methods
You can also define methods on an enum, which can be called on any of its instances.
enum! MyEnum, {
Variant(content)
}, {
-- Define methods in a second block
unwrap(item) {
return item.content
}
}
local instance = MyEnum.Variant("hello")
print(instance:unwrap()) -- Output: hello
Enum Decorators
Decorators can be applied to an entire enum! definition or to individual variants within it. This allows for powerful meta-programming capabilities, such as automatically adding serialization or marking variants as deprecated.
Enum Decorator
Apply a decorator to the entire enum by placing it before the enum! macro.
-- decorator that makes an enum printable
local printable = function(_enum)
_enum.func.to_string = function(item)
return f"<Enum {_enum.__name}:{item.__enum_var_name}>"
end
return _enum
end
enum! @printable Status, {
Ready,
InProgress,
Done
}
print(Status.Ready.to_string()) -- Output: <Enum Status:Ready>
Variant Decorator
Apply a decorator to a specific variant by placing it before the variant name.
-- decorator that marks something as deprecated
local deprecated = decorator! {
(_enum, variant) {
dynamic {
-- For function-like variants
return function(...)
print(f"Warning: Variant '{name}' is deprecated.")
return variant(...)
end
}
static {
-- For simple variants, we need to wrap it
print(f"Warning: Variant '{name}' is deprecated.")
return variant
}
}
}
enum! Message, {
NewMessage(string),
@deprecated
OldMessage(string)
}
local msg = Message.OldMessage("hello") -- Prints: Warning: Variant 'OldMessage' is deprecated.