Experimental Features

These features work in Luwu today. Their design isn't final yet.

Their syntax may change. Prefer the stable features on the other pages for code you'll keep.

Your editor reports them as disabled until you turn on their debug flags.

Push and pop operators

<+ adds values to a container. <- takes the last value back out.

They're a standard way to add to and take from any container. They work the way # works on anything that defines __len.

On a plain list, they add to and remove from the end:

local queue = {}
queue <+ "first"
queue <+ "second", "third"
print(#queue)

const last = <-queue
print(last, #queue)

Nil values are skipped and never leave a hole in the array.

A class joins in by defining __push and __pop. Then the same operators work on it, with its own rules.

This inventory holds at most two items. Code that fills it doesn't need to know that:

class Inventory(capacity: number)
    items: { string } = {}

    function __push(self, ...: string)
        for _, item in { ... } do
            if #self.items < self.capacity then
                table.insert(self.items, item)
            end
        end
    end
    function __pop(self): string?
        return table.remove(self.items)
    end
    function __len(self): number
        return #self.items
    end
end

const list = {}
list <+ "sword", "shield", "potion"

const bag = Inventory(2)
bag <+ "sword", "shield", "potion"

print(#list, #bag)
print(<-list, <-bag)

The pop syntax isn't decided yet. It may change.

match expressions

A match expression picks a value based on what another value looks like.

Each case is checked in order. The else arm is required.

const function describe(count: number): string
    return match count
        case 0 then "none"
        case 1 | 2 | 3 then "a few"
        else "many"
end

print(describe(0), describe(2), describe(50))

Matching objects

case is Class matches objects of a class. Add a pattern to pull out their fields.

A case can add when conditions, like if local.

class Circle(radius: number) end
class Rect(width: number, height: number) end

const function describe(shape: Circle | Rect): string
    return match shape
        case is Circle.{ radius } then `circle with radius {radius}`
        case is Rect.{ width, height } when width == height then `square of {width}`
        case is Rect.{ width, height } then `{width} by {height} rectangle`
        else "unknown shape"
end

print(describe(Circle(2)), describe(Rect(3, 3)), describe(Rect(2, 5)))