API Reference
Error
Error.new(name: string, message: string, tags: Table?)
Create an error object with a specified name and message.
In native Lua, errors can only be string values. At Roblox, we can take advantage of throwing error objects to provide structured information about problems that occur.
The tags table stores rich information about an error which can be provided when it is thrown, and later passed to a logging endpoint.
Throwing an error instance captures its stack trace, avoiding the need to explicitly use xpcall.
Fields
Name | Description |
---|---|
name: string |
The name of the error |
message: string |
A message which will be formatted with Dash.format if the error is thrown |
tags: Table |
A table to store custom rich information about the error |
stack: string? |
The value of debug.traceback() when the error is thrown |
Methods
Name | Description |
---|---|
:joinTags(tags: Table?) |
Return a new error instance containing the tags provided joined to any existing tags of the current error instance. |
:throw(tags: Table?) |
Throw an error. The stack of the error is captured and stored. If tags are provided, a new error is created and thrown with the joined tags of this instance. |
Static Methods
Name | Description |
---|---|
.new(name: string, message: string, tags: Table?) |
Returns a new Error instance |
.is(other: any) |
Returns true if other is an Error instance |
Usage
In general, errors should not be used during normal control flow.
None
A symbol representing nothing, that can be used in place of nil as a key or value of a table, where nil is illegal.
Utility functions can check for the None symbol and treat it like a nil value.
Usage
Use cases include:
- Creating an ordered list with undefined values in it
- Creating a map with a key pointing to a nil value
Symbol
Create a symbol with a specified name. Upper snake-case is recommended as the symbol is a constant, unless you are linking the symbol conceptually to a different string.
Symbols are useful when you want a value that isn't equal to any other type, for example if you want to store a unique property on an object that won't be accidentally accessed with a simple string lookup.
Static Methods
Name | Description |
---|---|
.new(name: string) |
Returns a new unique Symbol instance with called name |
.is(other: any) |
Returns true if other is a Symbol instance |
Example
local CHEESE = Symbol.new("CHEESE")
local FAKE_CHEESE = Symbol.new("CHEESE")
print(CHEESE == CHEESE) --> true
print(CHEESE == FAKE_CHEESE) --> false
print(tostring(CHEESE)) --> "Symbol.new(CHEESE)"
append
append<T>(target: Types.Array<T>, ...: Types.Array<T>): Types.Array<T>
Adds new elements to the target Array from subsequent Array arguments in left-to-right order.
Arguments which are nil
or None are skipped.
assertEqual
assertEqual(left: any, right: any, formattedErrorMessage: string?)
Performs a simple equality check and throws an error if left is not equal to right.
The formatted error message can be customized, which by default provides a serialization of both inputs using Dash.pretty.
The left
and right
values are available to be referenced in the formatted message.
assign
assign(target: Table, ...: Args<Table>): Table
Adds new values to target from subsequent Table arguments in left-to-right order.
Examples
local characters = {
Frodo = {
name = "Frodo Baggins",
team = "blue"
},
Boromir = {
score = 5
}
}
local otherCharacters = {
Frodo = {
team = "red",
score = 10
},
Bilbo = {
team = "yellow",
},
Boromir = {
score = {1, 2, 3}
}
}
local result = assign(characters, otherCharacters)
print(result) --[[
--> {
Frodo = {
team = "red",
score = 10
},
Bilbo = {
team = "yellow"
},
Boromir = {
score = {1, 2, 3}
}
}
]]
See
- Dash.join for an immutable alternative
class
Create a class called name with the specified constructor. The constructor should return a
plain table which will be turned into an instance of Class from a call to Class.new(...)
.
Instance Methods
Name | Description |
---|---|
:toString(): string |
Returns a string representation of the class |
:equals(other: any):boolean |
Returns true if the instance is equal to other |
:_init() |
A private function which is called once the instance has been initialized |
Static Methods
Name | Description |
---|---|
.new(...): Table |
Returns a new instance of the class |
.isInstance(value: any): boolean |
Returns true if value is an instance of the class |
Examples
-- Create a simple Vehicle class
local Vehicle = class("Vehicle", function(wheelCount: number) return
{
speed = 0,
wheelCount = wheelCount
}
end)
function Vehicle:drive(speed)
self.speed = speed
end
-- Create a car instance
local car = Vehicle.new(4)
car.wheelCount --> 4
car.speed --> 0
-- Drive the car
car:drive(10)
car.speed --> 10
Usage
- When using Dash classes, private fields should be prefixed with
_
to avoid accidental access. - A private field should only be accessed by a method of the class itself, though Dash does not restrict this in code.
- Public fields are recommended when there is no complex access logic e.g.
position.x
collect
collect(input: Types.Table, handler: CollectHandler): Types.Map<any, any>
Collect returns a new Table derived from input by iterating through its pairs and calling
the handler on each (key, child)
tuple.
The handler should return a new (newKey, value)
tuple to be inserted into the returned Table,
or nil
if no value should be added.
collectArray
collectArray(input: Types.Table, handler: Types.AnyFunction)
Collect returns a new Array derived from input by iterating through its pairs and calling
the handler on each (key, child)
tuple.
The handler should return a new value to be pushed onto the end of the result array, or nil
if no value should be added.
collectSet
collectSet(input: Types.Table, handler: Types.AnyFunction?)
Build a set from the entries of the input Table, calling handler on each entry and using the returned value as an element to add to the set.
If handler is not provided, values of input
are used as elements.
compose
compose(...: Types.Array<Types.AnyFunction>): Types.AnyFunction
Returns a function that calls the argument functions in left-right order on an input, passing the return of the previous function as argument(s) to the next.
Example
local function fry(item)
return "fried " .. item
end
local function cheesify(item)
return "cheesy " .. item
end
local prepare = compose(fry, cheesify)
prepare("nachos") --> "cheesy fried nachos"
copy
copy(input: Types.Table): Types.Table
Returns a shallow copy of the input Table.
cycles
cycles(value: any, initialCycles: Cycles?): Cycles
Get information about the number of times references to the same table values appear in a data structure.
Operates on cyclic structures, and returns a Cycles object for a given value by walking it recursively.
Cycles
Name | Type | Description |
---|---|---|
omit |
Array<any> |
An array of keys which should not be visited |
visited |
Set<Table> |
A set of tables which were visited recursively |
refs |
Map<Table, number> |
A map from table to unique index in visit order |
nextRef |
number |
The number to use for the next unique table visited |
endsWith
endsWith(input: string, suffix: string)
Checks if input ends with the string suffix.
Examples
endsWith("Fun Roblox Games", "Games") --> true
endsWith("Bad Roblox Memes", "Games") --> false
filter
filter(input: Types.Table, handler: FilterHandler): Types.Array<any>
Filter the input Table by calling the handler on each (child, index)
tuple.
For an Array input, the order of elements is prevered in the output.
The handler should return truthy to preserve the value in the resulting Table.
find
find(input: Types.Table, handler: FindHandler)
Returns an element in the input Table that the handler returns true
for, when passed the
(child, key)
entry.
Returns nil if no entires satisfy the condition.
For an Array, this first matching element is returned. For a Map, an arbitrary matching element is returned if it exists.
See
- Dash.first for a function which returns the first element of an Array matching a condition.
findIndex
findIndex(input: Types.Array<any>, handler: FindHandler)
Returns the index of the first element in the input Array that the handler returns true
for,
when passed the (child, key)
entry.
Returns nil if no entires satisfy the condition.
flat
flat(input: Types.Array<Types.Array<any>>): Types.Array<any>
Flattens the input array by a single level. Outputs a new Array of elements merged from the input Array arguments in left-to-right order.
forEach
forEach(input: Types.Table, handler: Handler<Value>): ()
Iterates through the elements of the input Table.
If the table is an Array, it iterates in order 1..n.
If the table is a Map, the keys are visited in an arbitrary order.
Calls the handler for each entry.
forEachArgs
forEachArgs(handler: Handler<Value>, ...: Args<Value>): ()
Iterates through the tail arguments in order, including nil values up to the argument list length.
Calls the Handler handler for each entry.
format
format(formatString: string, ...)
Returns the format string with placeholders {...}
substituted with readable representations
of the subsequent arguments.
This function is a simpler & more powerful version of string.format
, inspired by format!
in Rust.
{}
formats and prints the next argument using:format()
if available, or a suitable default representation depending on its type.{blah}
formats and prints the key "blah" of the 1st argument{2}
formats and prints the 2nd argument.{#2}
prints the length of the 2nd argument. Display parameters can be combined after a:
in the curly braces. Any format parameters used instring.format
can be used here, along with these extras:{:?}
formats any value usingpretty
.{:#?}
formats any value using multilinepretty
.
Examples
local props = {"teeth", "claws", "whiskers", "tail"}
format("{} is in {:#?}", "whiskers", props)
--> [[whiskers is in {"teeth", "claws", "whiskers", "tail"}]]
format("The time is {:02}:{:02}", 2, 4) -> "The time is 02:04"
format("The color blue is #{:06X}", 255) -> "The color blue is #0000FF"
Usage
- Escape
{
with{{
and}
similarly with}}
. - See https://developer.roblox.com/articles/Format-String for complete list of formating options and further use cases.
formatValue
formatValue(value: any, displayString: string): string
Format a specific value using the specified displayString.
Examples
formatValue(255, "06X") --> "0000FF"
formatValue(255.5) --> "255.5"
See
- Dash.format - see format for a full description of valid display strings.
freeze
freeze(objectName: string, object: Table, throwIfMissing: boolean?): Table
Returns a new read-only view of object which prevents any values from being changed.
Parameters
Name | Description |
---|---|
name |
The name of the object for improved error message readability. |
throwIfMissing |
If true then access to a missing key will also throw. |
Notes
Unfortunately you cannot iterate using pairs
or ipairs
on frozen objects because Luau doesn't support defining these custom iterators in metatables.
Example
local drink = freeze("Ice Cream", {
flavor = "mint",
topping = "sprinkles"
}, true)
print(drink.flavor) --> "mint"
drink.flavor = "vanilla"
--!> ReadonlyKey: Attempt to write to readonly key "flavor" (a string) of frozen object "Ice Cream"
print(drink.syrup) --> nil
--!> MissingKey: Attempt to read missing key "syrup" (a string) of frozen object "Ice Cream"
getOrSet
getOrSet(input: Types.Table, key: any, getValue: GetValueHandler)
Returns a value of the input Table at the key provided. If the key is missing, the value is acquired from the getValue handler, added to the input Table and returned.
groupBy
groupBy(input: Dash.Table, getKey: any)
Groups values in the input Table by their getKey value.
Each value of the result Table is an Array of values from the input Table which were assigned the corresponding key.
If getKey is a function, it is called with each (child, key)
entry and uses the return
value as the corresponding key to insert at in the result Table. Otherwise, the getKey value
is used directly as the key itself.
Example
local output = groupBy({
bike = {
name = "bike",
color = "blue"
},
car = {
name = "car",
color = "red"
},
van = {
name = "van",
color = "white"
},
ghost = {
name = "ghost"
}
}, "color")
--[[
Output: {
blue = {
{
color = "blue",
name = "bike"
}
},
red = {
{
color = "red",
name = "car"
}
},
white = {
{
color = "white",
name = "van"
}
}
}
]]
identity
identity(...)
The identity function, which simply returns its input parameters.
Can be used to make it clear that a handler returns its inputs.
includes
includes(source: Table, value: any): boolean
Returns true if the item exists as a value in the source Table.
isCallable
isCallable(value: any): boolean
Returns true
if the value can be called i.e. you can write value(...)
.
isLowercase
isLowercase(input: string): boolean
Returns true
if the first character of input is a lower-case character.
Throws if the input is not a string or it is the empty string.
Our current version of Lua unfortunately does not support upper or lower-case detection outside the english alphabet. This function has been implemented to return the expected result once this has been corrected.
isUppercase
isUppercase(input: string): boolean
Returns true
if the first character of input is an upper-case character.
Throws if the input is not a string or it is the empty string.
Our current version of Lua unfortunately does not support upper or lower-case detection outside the english alphabet. This function has been implemented to return the expected result once this has been corrected.
join
join(...): Types.Map<any, any>
Output a new Map from merging all the keys in the Map arguments in left-to-right order.
See
- Dash.assign for a mutable alternative
joinDeep
joinDeep(source: Types.Map<any, any>, delta: Types.Map<any, any>): Types.Map<any, any>
Creates a shallow clone of the source Map, and copies the values from the delta Map by key, like the join utility.
However, if any of the values are tables themselves, the joinDeep function is called recursively to produce a new table at the specified key.
The purpose of this function is to merge nested immutable data using as few table creation operations as possible, making it appropriate for updating state in a reducer.
Usage
- The None symbol can be used to remove an existing value.
Example
local source = {
name = "car",
lights = {
front = 2,
back = 2,
indicators = {
color = "orange"
},
brake = {
color = "red"
}
},
tyres = 4
}
local delta = {
name = "bike",
lights = {
front = 3,
indicators = {
rate = 20
}
},
tyres = None
}
local output = joinDeep(source, delta)
[[
Output: {
lights = {
back = 2,
brake = {
color = "red"
},
front = 3,
indicators = {
color = "orange",
rate = 20
}
},
name = "bike"
}
]]
keyBy
keyBy(input: Types.Table, getKey: any): Types.Table
Assigns values in the input Table by their getKey value.
If getKey is a function, it is called with each (child, key)
entry and uses the return
value as the corresponding key to assign to in the result Table. Otherwise, the getKey value
is used directly as the key itself.
Example
local output = keyBy({
bike = {
name = "bike",
color = "blue"
},
car = {
name = "car",
color = "red"
},
van = {
name = "van",
color = "white"
},
ghost = {
name = "ghost"
}
}, "color")
[[
Output: {
blue = {
color = "blue",
name = "bike"
},
red = {
color = "red",
name = "car"
},
white = {
color = "white",
name = "van"
}
}]]
keys
keys(input: Types.Table): Types.Array<any>
Returns an Array of the keys in the input Table.
If the input is an Array, ordering is preserved.
If the input is a Map, elements are keys in an arbitrary order.
last
last(input: Types.Table): Types.Array<any>
Returns the last element in the input Array that the handler returns true
for, when
passed the (child, index)
entry.
Returns nil if no entires satisfy the condition.
If handler is not defined, the function simply returns the last element of the Array.
leftPad
leftPad(input: string, length: number, prefix: string?): string
Makes a string of length
from input
by repeating characters from prefix
at the start of the string.
Params
prefix
- default =""
Examples
leftPad("toast", 6) --> " toast"
leftPad("2", 2, "0") --> "02"
leftPad("toast", 10, ":)") --> ":):):toast"
map
map(input: Types.Array<any>, handler: MapHandler): Types.Array<any>
Iterates through the elements of the input Table.
For an Array input, the elements are visted in order 1..n.
For a Map input, the elements are visited in an arbitrary order.
Calls the handler for each entry and constructs a new Table using the same keys but replacing the values with new ones returned from the handler.
Values returned by handler must be defined.
See
- Dash.collectArray if you want to return nil values.
mapFirst
mapFirst(input: Types.Array<any>, handler: MapHandler)
Iterates through the elements of the input Array in order 1..n.
Calls the handler for each entry and returns the first non-nil value returned by the handler.
mapLast
mapLast(input: Types.Array<any>, handler: MapHandler)
Iterates through the elements of the input Array in reverse in order n..1.
Calls the handler for each entry and returns the first non-nil value returned by the handler.
mapOne
mapOne(input: Types.Array<any>, handler: MapHandler?)
Iterates through the elements of the input Table in no particular order.
Calls the handler for each entry and returns the first non-nil value returned by the handler.
If handler is nil
, the first value visited is returned.
noop
noop()
A function which does nothing.
Can be used to make it clear that a handler has no function.
omit
omit(input: Types.Table, keys: Types.Array<any>): Types.Table
Return a new Table made from entries in the input Table whose key is not in the keys Array.
If the input is an Array, ordering is preserved.
If the input is a Map, elements are returned in an arbitrary order.
pretty
pretty(object: any, options: PrettyOptions?): string
Return a pretty string serialization of object.
This implementation deals with cycles in tables and can neatly display metatables.
Optionally use an indented multiline string, limit the depth of tables, omit or pick keys.
PrettyOptions
Name | Type | Description |
---|---|---|
depth |
number? |
The maximum depth of ancestors of a table to display |
omit |
Array<any>? |
An array of keys which should not be visited |
multiline |
boolean? |
Whether to use multiple lines (default = false) |
noQuotes |
boolean? |
Whether to drop the quotation marks around strings. By default, this is true for table keys |
indent |
string? |
The indent string to use (default = "\t") |
visited |
Set<Table>? |
A set of tables which have already been visited and should be referred to by reference |
cycles |
Cycles? |
A cycles object returned from cycles to aid reference display |
See
reduce
reduce(input: Types.Array<any>, handler: ReduceHandler, initial: any)
Iterate through the elements of the input Array in order 1..n.
Call the handler for each element, passing the return of the previous call as the first argument.
The initial value is passed into the first call, and the final value returned by the function.
reverse
reverse(input: Types.Array<any>): Types.Array<any>
Reverse the order of the elements in the input Array.
rightPad
rightPad(input: string, length: number, suffix: string?): string
Makes a string of length
from input
by repeating characters from suffix
at the end of the string.
By default, suffix is " "
.
Examples
rightPad("toast", 6) --> "toast "
rightPad("2", 2, "!") --> "2!"
rightPad("toast", 10, ":)") --> "toast:):):"
shallowEqual
shallowEqual(left: any, right: any)
Returns true
if the left and right values are equal (by the equality operator) or the
inputs are tables, and all their keys are equal.
slice
slice(input: Types.Array<any>, left: number?, right: number?)
Return a portion of the input Array starting with the element at the left index and ending with the element at the right index (i.e. an inclusive range)
If left is not defined, it defaults to 1. If right is not defined, it defaults to the length of the array (i.e. the last element)
If left is -n
, the slice starts with the element n
places from the last one.
If right is -n
, the slice ends with the element n
places from the last one.
An empty array is returned if the slice has no or negative length.
some
some(input: Types.Map<any, any>, handler: SomeHandler?): boolean
Iterates through the elements of the input Table in no particular order.
Calls the handler for each entry and returns true
if the handler returns truthy for any
element which it is called with.
splitOn
splitOn(input: string, pattern: string): Types.Array<string>
Splits input into parts based on a pattern delimiter and returns a Table of the parts, followed by a Table of the matched delimiters.
startsWith
startsWith(input: string, prefix: string): boolean
Checks if input starts with the string start.
Examples
startsWith("Fun Roblox Games", "Fun") --> true
startsWith("Chess", "Fun") --> false
trim
trim(input: string): string
Remove any whitespace at the start and end of the input string.
values
values(input: Types.Map<any, any>): Types.Array<any>
Returns an Array of the values in the input Table.
If the input is an Array, ordering is preserved.
If the input is a Map, values are returned in an arbitrary order.