collectionsAdded by Luwu.
LuwuAvailable in luwu/integration; this feature is unstable and may change without a semver bump.
Needs the DebugLuwuCollections FFlag.
experimental
DebugLuwuCollections FFlag.collections provides the data structures you'd otherwise build out of tables: bundles of two to four values, an ordered map that remembers insertion order, growable arrays, double-ended queues, and options and results for values that can be missing or can fail. They're builtin classes implemented in C++ that the type checker fully understands.
option and result are tables that hold their variant classes. The types have the same names and come from the library the way a required module's types do:
const .{ vec } = collections
type .{ vec } = collections
const scores: vec<number> = vec({ 10, 20 })
scores:push(30)
print(#scores)3
The library is a prototype, and its API can still change.
Summary
Bundles
class pair<A, B>(public const first: A, public const second: B)collections.pairAdded by Luwu.
LuwuAvailable in luwu/integration; this feature is unstable and may change without a semver bump.
Needs the
experimentalDebugLuwuCollectionsFFlag.- Two values kept together
class triple<A, B, C>(public const first: A, public const second: B, public const third: C)collections.tripleAdded by Luwu.
LuwuAvailable in luwu/integration; this feature is unstable and may change without a semver bump.
Needs the
experimentalDebugLuwuCollectionsFFlag.- Three values kept together
class quad<A, B, C, D>( public const first: A, public const second: B, public const third: C, public const fourth: D )collections.quadAdded by Luwu.
LuwuAvailable in luwu/integration; this feature is unstable and may change without a semver bump.
Needs the
experimentalDebugLuwuCollectionsFFlag.- Four values kept together
Containers
class orderedmap<K, V>() function get(self, key: K): V? function set(self, key: K, value: V) function has(self, key: K): boolean function remove(self, key: K): V? function insert(self, position: number, key: K, value: V) function move(self, key: K, position: number) function movebefore(self, key: K, other: K) function moveafter(self, key: K, other: K) function swap(self, a: K, b: K) function sort(self, comesbefore: (K, K) -> boolean) function index(self, key: K): number? function at(self, position: number): (K?, V?) endcollections.orderedmapAdded by Luwu.
LuwuAvailable in luwu/integration; this feature is unstable and may change without a semver bump.
Needs the
experimentalDebugLuwuCollectionsFFlag.- A map whose entries stay in insertion order
class vec<T>(items: { T }?) function push(self, value: T) function pop(self): T? function at(self, position: number): T? function set(self, position: number, value: T) function insert(self, position: number, value: T) function remove(self, position: number): T function clear(self) endcollections.vecAdded by Luwu.
LuwuAvailable in luwu/integration; this feature is unstable and may change without a semver bump.
Needs the
experimentalDebugLuwuCollectionsFFlag.- A growable array that holds one type of value
class vecdeque<T>(items: { T }?) function pushfront(self, value: T) function pushback(self, value: T) function popfront(self): T? function popback(self): T? function front(self): T? function back(self): T? function at(self, position: number): T? function set(self, position: number, value: T) function clear(self) endcollections.vecdequeAdded by Luwu.
LuwuAvailable in luwu/integration; this feature is unstable and may change without a semver bump.
Needs the
experimentalDebugLuwuCollectionsFFlag.- A double-ended queue with constant-time adds and takes at either end
Options and results
export type option<T> = some<T> | none class some<T>(public const value: T) function get(self): T function expect(self, message: string?): T end declare collections: { option: { some: class<some>, none: none }, }collections.optionAdded by Luwu.
LuwuAvailable in luwu/integration; this feature is unstable and may change without a semver bump.
Needs the
experimentalDebugLuwuCollectionsFFlag.- A value that may be missing
export type result<T, E> = ok<T> | err<E> class ok<T>(public const value: T) function ok(self): T function err(self): none function expect(self, message: string?): T end class err<E>( public const error: E, public const module: string?, public const line: number?, public const traceback: string? ) function ok(self): none function err(self): E function expect(self, message: string?): never end declare collections: { result: { ok: class<ok>, err: class<err> }, }collections.resultAdded by Luwu.
LuwuAvailable in luwu/integration; this feature is unstable and may change without a semver bump.
Needs the
experimentalDebugLuwuCollectionsFFlag.- The outcome of something that can fail: a value or an error
Bundles
collections.pairAdded by Luwu.
LuwuAvailable in luwu/integration; this feature is unstable and may change without a semver bump.
Needs the DebugLuwuCollections FFlag.
experimental
DebugLuwuCollections FFlag.class pair<A, B>(public const first: A, public const second: B)Two values kept together, like a function's two results stored in one place. The fields are const: build a new pair to change them.
==compares two pairs field by field with==.tostringwrites the call that builds an equal pair:pair("x", 1).- A
forloop gives each position and its value in order,nilincluded. - Destructuring reads the fields by position:
const .(a, b) = p.
const .{ pair } = collections
const point = pair("x", 4)
const .(axis, offset) = point
print(`{axis} = {offset}`)
print(point == pair("x", 4))
print(tostring(point))x = 4
true
pair("x", 4)collections.tripleAdded by Luwu.
LuwuAvailable in luwu/integration; this feature is unstable and may change without a semver bump.
Needs the DebugLuwuCollections FFlag.
experimental
DebugLuwuCollections FFlag.class triple<A, B, C>(public const first: A, public const second: B, public const third: C)Three values kept together. It works like pair with a third field.
collections.quadAdded by Luwu.
LuwuAvailable in luwu/integration; this feature is unstable and may change without a semver bump.
Needs the DebugLuwuCollections FFlag.
experimental
DebugLuwuCollections FFlag.class quad<A, B, C, D>(
public const first: A,
public const second: B,
public const third: C,
public const fourth: D
)Four values kept together. It works like pair with a third and fourth field.
Containers
collections.orderedmapAdded by Luwu.
LuwuAvailable in luwu/integration; this feature is unstable and may change without a semver bump.
Needs the DebugLuwuCollections FFlag.
experimental
DebugLuwuCollections FFlag.class orderedmap<K, V>()
function get(self, key: K): V?
function set(self, key: K, value: V)
function has(self, key: K): boolean
function remove(self, key: K): V?
function insert(self, position: number, key: K, value: V)
function move(self, key: K, position: number)
function movebefore(self, key: K, other: K)
function moveafter(self, key: K, other: K)
function swap(self, a: K, b: K)
function sort(self, comesbefore: (K, K) -> boolean)
function index(self, key: K): number?
function at(self, position: number): (K?, V?)
endA map whose entries stay in insertion order. A table's pairs visits keys in no particular order, and an orderedmap visits them in order for a menu, a leaderboard or the columns of a table. Finding the position of a key or the entry at a position takes constant time.
setchanges the value of a key the map has and adds a new key at the end. A key can't benilor NaN. Setting a value tonilkeeps the key: useremoveto take it out.removereturns the removed value, ornilwhen the map didn't have the key.insertadds a new key atpositionand moves the entries from there on back by one. For a key the map has, it moves that entry there and sets its value.movemoves a key to a position.movebeforeandmoveaftermove a key right before or afterother.swaptrades the positions of two keys. Each raises an error when the map doesn't have a key it's given.sortputs the entries in a stable order by their keys.comesbeforereturnstruewhen its first key goes before its second.indexreturns the position of a key.atreturns the key and value at a position, or twonils when there's no entry there.#gives the number of entries, and aforloop gives each key and value in order. Removing the key the loop is on raises an error at the next step.
A position is a whole number from 1 to the number of entries (one more for insert). Any other position passed to insert or a move raises an error.
const .{ orderedmap } = collections
const stock = orderedmap()
stock:set("pears", 4)
stock:set("apples", 12)
stock:insert(1, "kiwis", 7)
stock:moveafter("kiwis", "apples")
for fruit, count in stock do
print(`{fruit}: {count}`)
end
print(stock:index("kiwis"))pears: 4 apples: 12 kiwis: 7 3
collections.vecAdded by Luwu.
LuwuAvailable in luwu/integration; this feature is unstable and may change without a semver bump.
Needs the DebugLuwuCollections FFlag.
experimental
DebugLuwuCollections FFlag.class vec<T>(items: { T }?)
function push(self, value: T)
function pop(self): T?
function at(self, position: number): T?
function set(self, position: number, value: T)
function insert(self, position: number, value: T)
function remove(self, position: number): T
function clear(self)
endA growable array that holds one type of value. The first value it gets fixes the type: a vec of numbers raises an error when you push a string, and a vec of objects takes objects of the same class only. nil never goes in. The optional array passed to the constructor fills the vec in order.
pushadds a value at the end andpoptakes the last one off, or returnsnilwhen the vec is empty.atreturns the value at a position, ornilwhen there's none there.setreplaces the value at a position the vec has.insertadds a value at a position from 1 to one past the end and moves the values after it back.removetakes out the value at a position and returns it.clearempties the vec. The element type stays fixed.#gives the length, aforloop gives each position and value, andtostringwrites the call that builds an equal vec:vec({1, 2}).
set, insert and remove raise an error for a position out of range.
const .{ vec } = collections
const names = vec({ "Ada", "Grace" })
names:push("Linus")
names:insert(1, "Alan")
print(names:remove(3))
print(tostring(names))
const ok = pcall(function()
names:push(42)
return true
end)
print(ok)Grace
vec({"Alan", "Ada", "Linus"})
falsecollections.vecdequeAdded by Luwu.
LuwuAvailable in luwu/integration; this feature is unstable and may change without a semver bump.
Needs the DebugLuwuCollections FFlag.
experimental
DebugLuwuCollections FFlag.class vecdeque<T>(items: { T }?)
function pushfront(self, value: T)
function pushback(self, value: T)
function popfront(self): T?
function popback(self): T?
function front(self): T?
function back(self): T?
function at(self, position: number): T?
function set(self, position: number, value: T)
function clear(self)
endA double-ended queue: adding and taking values at either end takes constant time. Taking the first value of an array with table.remove(t, 1) moves every other value down. A vecdeque takes it without moving the rest. Like vec, it holds one type of value fixed by the first one it gets.
pushfrontandpushbackadd a value at the front or the back.popfrontandpopbacktake one off, or returnnilwhen the queue is empty.frontandbackreturn the value at either end without removing it.atandsetread and replace values by position from the front, starting at 1.clear,#,forloops andtostringwork as they do forvec.
const .{ vecdeque } = collections
const jobs = vecdeque({ "build", "test" })
jobs:pushback("deploy")
jobs:pushfront("fetch")
while #jobs > 0 do
print(jobs:popfront())
endfetch build test deploy
Options and results
collections.optionAdded by Luwu.
LuwuAvailable in luwu/integration; this feature is unstable and may change without a semver bump.
Needs the DebugLuwuCollections FFlag.
experimental
DebugLuwuCollections FFlag.export type option<T> = some<T> | none
class some<T>(public const value: T)
function get(self): T
function expect(self, message: string?): T
end
declare collections: {
option: { some: class<some>, none: none },
}A value that may be missing. A full option is a some object that holds the value, and an empty option is none itself. option.none is the same none and allocates nothing.
option.some(value)raises an error whenvalueisnilornone.getreturns the value, andnone:get()returnsnone.expectreturns the value.none:expect(message)raises an error withmessage, or with"expected a value, but got none"when you leave it out.==compares the values of twosomeobjects, andtostringwritesoption.some(5).
none has get and expect only while the library is loaded. Indexing none with any other key is an error.
const .{ option } = collections
type .{ option } = collections
const function find_user(id: number): option<string>
return if id == 1 then option.some("Ada") else option.none
end
print(find_user(1):get())
print(find_user(2):get() == none)
print(tostring(find_user(1)))Ada
true
option.some("Ada")collections.resultAdded by Luwu.
LuwuAvailable in luwu/integration; this feature is unstable and may change without a semver bump.
Needs the DebugLuwuCollections FFlag.
experimental
DebugLuwuCollections FFlag.export type result<T, E> = ok<T> | err<E>
class ok<T>(public const value: T)
function ok(self): T
function err(self): none
function expect(self, message: string?): T
end
class err<E>(
public const error: E,
public const module: string?,
public const line: number?,
public const traceback: string?
)
function ok(self): none
function err(self): E
function expect(self, message: string?): never
end
declare collections: {
result: { ok: class<ok>, err: class<err> },
}The outcome of something that can fail: an ok object with a value or an err object with an error. A function that returns a result makes its caller handle the failure instead of catching an error it raised.
okreturns the value of anokandnonefor anerr.errdoes the opposite.expectreturns the value of anok. On anerrit raises the error, withmessageand a colon in front when you pass one.- An
err'smodule,lineandtracebacksay where its error was raised. Atryexpression fills them in, andtostringadds them after the error. ==compares two objects of the same variant by their value or error.
A try expression runs an expression and gives a result: ok with its value, or err with the error it raised.
const .{ result } = collections
type .{ result } = collections
const function parse_port(text: string): result<number, string>
const port = tonumber(text)
if port and port >= 1 and port <= 65535 then
return result.ok(port)
end
return result.err(`'{text}' is not a port`)
end
print(parse_port("8080"):ok())
print(parse_port("http"):err())
print(tostring(try tonumber("12")))8080 'http' is not a port result.ok(12)