Structs and traits
Structs, traits, and impls emit the metatable pattern
UpdatedAn Alloy struct is a plain table that vanilla Luau can use. Fields carry defaults and read or write marks. impl adds methods. A trait is a type of signatures plus default bodies.
Alloystructs.aly
1struct Vec2 2 x: number 3 y: number = 0 4end 5impl Vec2 6 function len(self): number 7 return math.sqrt(self.x ^ 2 + self.y ^ 2) 8 end 9end 10local v = new Vec2 { x = 3, y = 4 }
Emitted Luausame line count
1local __alloy = require("@alloy") local Vec2 = {} Vec2.__index = Vec2 2 3 4 type Vec2 = typeof(setmetatable({} :: { x: number, y: number }, Vec2)) setmetatable(Vec2, { __call = function(_, f: { x: number, y: number? }): Vec2 if f.y == nil then local _y: number = 0 f.y = _y end return ((setmetatable(f, Vec2) :: any) :: Vec2) end }) function Vec2.new(f: { x: number, y: number? }): Vec2 return Vec2(f) end Vec2.__tostring = function(s) return __alloy.show_struct("Vec2", s, { "x", "y" }) end 5do 6 function Vec2.len(self: Vec2): number 7 return math.sqrt(self.x ^ 2 + self.y ^ 2) 8 end 9end 10local v = Vec2({ x = 3, y = 4 }) return nil
newis the only way in.new Vec2 { ... }is the fields form; a struct whose impl writesneworNewtakesnew Vec2(...)instead. BareVec2 { }andVec2(1, 2)are diagnostics.@derive(Eq, Debug, Clone, Serialize)is pure codegen from the field list.- Operator traits map to metamethods:
impl Add for Vec2puts__addon the instance metatable. - Generic bounds
<T: Shape>become(T & Shape)on each parameter.
