Table Comprehensions

A table comprehension builds a new table from a loop, in one expression.

In Luau, you'd create an empty table and fill it:

const numbers = { 1, 2, 3, 4 }

local doubled = {}
for _, n in numbers do
    table.insert(doubled, n * 2)
end
print(#doubled)

In Luwu, you write the loop inside the table:

const numbers = { 1, 2, 3, 4 }

const doubled = { for _, n in numbers give n * 2 }
print(#doubled)

give says what goes into the table for each item.

Comprehensions are also faster because Luwu sizes the table up front instead of growing it.

Filtering with when

Add when clauses to skip items. They work like the ones in if local.

const scores: { [string]: number? } = { ada = 92, alan = 67, grace = 88 }

const passed = {
    for name, score in scores
    when score >= 70
    give name
}
print(#passed)

A when clause can bind a value for the give to use:

const prices: { [string]: number? } = { apple = 1.25, pear = 0.8 }
const basket = { "apple", "kiwi", "pear" }

const costs = {
    for _, fruit in basket
    when const price = prices[fruit]
    give price * 2
}
print(costs[1], costs[2])

Building maps

Give [key] = value to build a map instead of an array.

const players = { "Ada", "Grace", "Alan" }

const name_lengths = {
    for _, player in players
    give [player] = #player
}
print(name_lengths.Grace)

[key] += value adds to the value already stored under that key.

const words = { "red", "blue", "red", "green", "red" }

const counts = {
    for _, word in words
    give [word] += 1
}
print(counts.red, counts.blue)

Destructuring items

The loop header can destructure each item.

const people = {
    { name = "Ada", age = 36 },
    { name = "Tom", age = 12 },
}

const adults = {
    for _, .{ name, age } in people
    when age >= 18
    give name
}
print(adults[1], #adults)

Several loops

Chain for clauses to loop inside a loop. This flattens a grid into an array:

const grid = {
    { 1, 0, 2 },
    { 0, 3, 0 },
}

const filled = {
    for _, row in grid
    for _, cell in row
    when cell ~= 0
    give cell
}
print(#filled)

Items that need statements

When one item takes a few steps, end the clauses with do instead of give. The block follows the rules of a do expression: it ends with give, and continue skips the item.

const lines = { "hp=10", "", "mp=four" }

const settings = {
    for _, line in lines
    when line ~= ""
    do
        const key, value = string.match(line, "^(%a+)=(%d+)$")
        value or continue
        give `{key}: {value}`
}
print(#settings, settings[1])

do is short for give do. You can write either.

Things to know