Arrays

Safety

Always limit the maximum size of arrays.

Arrays are first-class citizens in Rhai.

All elements stored in an array are Dynamic, and the array can freely grow or shrink with elements added or removed.

The Rust type of a Rhai array is rhai::Array which is an alias to Vec<Dynamic>.

type_of() an array returns "array".

Arrays are disabled via the no_index feature.

Literal Syntax

Array literals are built within square brackets [] and separated by commas ,:

[ value, value,, value ]

[ value, value,, value , ] // trailing comma is OK

Element Access Syntax

From beginning

Like C, arrays are accessed with zero-based, non-negative integer indices:

array [ index position from 0 to (length−1) ]

From end

A negative position accesses an element in the array counting from the end, with −1 being the last element.

array [ index position from −1 to −length ]

Built-in Functions

The following methods (mostly defined in the BasicArrayPackage but excluded when using a raw Engine) operate on arrays.

FunctionParameter(s)Description
getposition, counting from end if < 0gets a copy of the element at a certain position (() if the position is not valid)
set
  1. position, counting from end if < 0
  2. new element
sets a certain position to a new value (no effect if the position is not valid)
push, += operator
  1. array
  2. element to append (not another array)
appends an element to the end
append, += operator
  1. array
  2. array to append
concatenates the second array to the end of the first
+ operator
  1. first array
  2. second array
concatenates the first array with the second
== operator
  1. first array
  2. second array
are two arrays the same (elements compared with the == operator, if defined)?
!= operator
  1. first array
  2. second array
are two arrays different (elements compared with the == operator, if defined)?
insert
  1. position, counting from end if < 0, end if ≥ length
  2. element to insert
inserts an element at a certain position
popnoneremoves the last element and returns it (() if empty)
shiftnoneremoves the first element and returns it (() if empty)
extract
  1. start position, counting from end if < 0, end if ≥ length
  2. (optional) number of items to extract, none if ≤ 0, to end if omitted
extracts a portion of the array into a new array
extractrange of items to extract, from beginning if ≤ 0, to end if ≥ lengthextracts a portion of the array into a new array
removeposition, counting from end if < 0removes an element at a particular position and returns it (() if the position is not valid)
reversenonereverses the array
len method and propertynonereturns the number of elements
is_empty method and propertynonereturns true if the array is empty
pad
  1. target length
  2. element to pad
pads the array with an element to at least a specified length
clearnoneempties the array
truncatetarget lengthcuts off the array at exactly a specified length (discarding all subsequent elements)
choptarget lengthcuts off the head of the array, leaving the tail at exactly a specified length
split
  1. array
  2. position to split at, counting from end if < 0, end if ≥ length
splits the array into two arrays, starting from a specified position
drain
  1. function pointer to predicate (usually a closure), or the function name as a string
removes all items (returning them) that return true when called with the predicate function taking the following parameters:
  1. array item
  2. (optional) offset position
drain
  1. start position, counting from end if < 0, end if ≥ length
  2. number of items to remove, none if ≤ 0
removes a portion of the array, returning the removed items as a new array
drainrange of items to remove, from beginning if ≤ 0, to end if ≥ lengthremoves a portion of the array, returning the removed items as a new array
retain
  1. function pointer to predicate (usually a closure), or the function name as a string
removes all items (returning them) that do not return true when called with the predicate function taking the following parameters:
  1. array item
  2. (optional) offset position
retain
  1. start position, counting from end if < 0, end if ≥ length
  2. number of items to retain, none if ≤ 0
retains a portion of the array, removes all other items and returning them as a new array
retainrange of items to retain, from beginning if ≤ 0, to end if ≥ lengthretains a portion of the array, removes all other bytes and returning them as a new array
splice
  1. start position, counting from end if < 0, end if ≥ length
  2. number of items to remove, none if ≤ 0
  3. array to insert
replaces a portion of the array with another (not necessarily of the same length as the replaced portion)
splice
  1. range of items to remove, from beginning if ≤ 0, to end if ≥ length
  2. array to insert
replaces a portion of the array with another (not necessarily of the same length as the replaced portion)
filterfunction pointer to predicate (usually a closure), or the function name as a stringconstructs a new array with all items that return true when called with the predicate function taking the following parameters:
  1. array item
  2. (optional) offset position
contains, in operatorelement to finddoes the array contain an element? The == operator (if defined) is used to compare custom types
index_of
  1. element to find (not a function pointer)
  2. (optional) start position, counting from end if < 0, end if ≥ length
returns the position of the first item in the array that equals the supplied element (using the == operator, if defined), or −1 if not found
index_of
  1. function pointer to predicate (usually a closure), or the function name as a string
  2. (optional) start position, counting from end if < 0, end if ≥ length
returns the position of the first item in the array that returns true when called with the predicate function, or −1 if not found:
  1. array item
  2. (optional) offset position
dedup(optional) function pointer to predicate (usually a closure), or the function name as a string; if omitted, the == operator is used, if definedremoves all but the first of consecutive items in the array that return true when called with the predicate function (non-consecutive duplicates are not removed):
1st & 2nd parameters: two items in the array
mapfunction pointer to conversion function (usually a closure), or the function name as a stringconstructs a new array with all items mapped to the result of applying the conversion function taking the following parameters:
  1. array item
  2. (optional) offset position
reduce
  1. function pointer to accumulator function (usually a closure), or the function name as a string
  2. (optional) the initial value
reduces the array into a single value via the accumulator function taking the following parameters:
  1. accumulated value (() initially)
  2. array item
  3. (optional) offset position
reduce_rev
  1. function pointer to accumulator function (usually a closure), or the function name as a string
  2. (optional) the initial value
reduces the array (in reverse order) into a single value via the accumulator function taking the following parameters:
  1. accumulated value (() initially)
  2. array item
  3. (optional) offset position
somefunction pointer to predicate (usually a closure), or the function name as a stringreturns true if any item returns true when called with the predicate function taking the following parameters:
  1. array item
  2. (optional) offset position
allfunction pointer to predicate (usually a closure), or the function name as a stringreturns true if all items return true when called with the predicate function taking the following parameters:
  1. array item
  2. (optional) offset position
sortfunction pointer to a comparison function (usually a closure), or the function name as a stringsorts the array with a comparison function taking the following parameters:
  1. first item
  2. second item
    return value: INT < 0 if first < second, > 0 if first > second, 0 if first == second
sortnonesorts a homogeneous array containing only elements of the same comparable built-in type (INT, FLOAT, Decimal, string, character, bool, ())

Tip: Use custom types with arrays

To use a custom type with arrays, a number of functions need to be manually implemented, in particular the == operator in order to support the in operator which uses == (via the contains method) to compare elements.

See the section on custom types for more details.

Examples

let y = [2, 3];             // y == [2, 3]

let y = [2, 3,];            // y == [2, 3]

y.insert(0, 1);             // y == [1, 2, 3]

y.insert(999, 4);           // y == [1, 2, 3, 4]

y.len == 4;

y[0] == 1;
y[1] == 2;
y[2] == 3;
y[3] == 4;

(1 in y) == true;           // use 'in' to test if an item exists in the array

(42 in y) == false;         // 'in' uses the 'contains' function, which uses the
                            // '==' operator (that users can override)
                            // to check if the target item exists in the array

y.contains(1) == true;      // the above de-sugars to this

y[1] = 42;                  // y == [1, 42, 3, 4]

(42 in y) == true;

y.remove(2) == 3;           // y == [1, 42, 4]

y.len == 3;

y[2] == 4;                  // elements after the removed element are shifted

ts.list = y;                // arrays can be assigned completely (by value copy)

ts.list[1] == 42;

[1, 2, 3][0] == 1;          // indexing on array literal

[1, 2, 3][-1] == 3;         // negative position counts from the end

fn abc() {
    [42, 43, 44]            // a function returning an array
}

abc()[0] == 42;

y.push(4);                  // y == [1, 42, 4, 4]

y += 5;                     // y == [1, 42, 4, 4, 5]

y.len == 5;

y.shift() == 1;             // y == [42, 4, 4, 5]

y.chop(3);                  // y == [4, 4, 5]

y.len == 3;

y.pop() == 5;               // y == [4, 4]

y.len == 2;

for item in y {             // arrays can be iterated with a 'for' statement
    print(item);
}

y.pad(6, "hello");          // y == [4, 4, "hello", "hello", "hello", "hello"]

y.len == 6;

y.truncate(4);              // y == [4, 4, "hello", "hello"]

y.len == 4;

y.clear();                  // y == []

y.len == 0;

// The examples below use 'a' as the master array

let a = [42, 123, 99];

a.map(|v| v + 1);           // returns [43, 124, 100]

a.map(|v, i| v + i);        // returns [42, 124, 101]

a.filter(|v| v > 50);       // returns [123, 99]

a.filter(|v, i| i == 1);    // returns [123]

a.filter("is_odd");         // returns [123, 99]

a.filter(Fn("is_odd"));     // <- previous statement is equivalent to this...

a.filter(|v| is_odd(v));    // <- or this

a.some(|v| v > 50);         // returns true

a.some(|v, i| v < i);       // returns false

a.none(|v| v != 0);         // returns false

a.none(|v, i| v == i);      // returns true

a.all(|v| v > 50);          // returns false

a.all(|v, i| v > i);        // returns true

// Reducing - initial value provided directly
a.reduce(|sum, v| sum + v, 0) == 264;

// Reducing - initial value is '()'
a.reduce(
    |sum, v| if sum.type_of() == "()" { v } else { sum + v }
) == 264;

// Reducing - initial value has index position == 0
a.reduce(|sum, v, i|
    if i == 0 { v } else { sum + v }
) == 264;

// Reducing - initial value provided directly
a.reduce_rev(|sum, v| sum + v, 0) == 264;

// Reducing - initial value is '()'
a.reduce_rev(
    |sum, v| if sum.type_of() == "()" { v } else { sum + v }
) == 264;

// Reducing - initial value has index position == 0
a.reduce_rev(|sum, v, i|
    if i == 2 { v } else { sum + v }
) == 264;

// In-place modification

a.splice(1..=1, [1, 3, 2]); // a == [42, 1, 3, 2, 99]

a.extract(1..=3);           // returns [1, 3, 2]

a.sort(|x, y| y - x);       // a == [99, 42, 3, 2, 1]

a.sort();                   // a == [1, 2, 3, 42, 99]

a.drain(|v| v <= 1);        // a == [2, 3, 42, 99]

a.drain(|v, i| i ≥ 3);      // a == [2, 3, 42]

a.retain(|v| v > 10);       // a == [42]

a.retain(|v, i| i > 0);     // a == []