rhai/doc/src/language/arrays.md
2020-10-14 21:27:31 +08:00

16 KiB

Arrays

{{#include ../links.md}}

Arrays are first-class citizens in Rhai. Like C, arrays are accessed with zero-based, non-negative integer indices:

array [ index ]

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

[ value , value , ... , value ]

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

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.

[type_of()] an array returns "array".

Arrays are disabled via the [no_index] feature.

The maximum allowed size of an array can be controlled via Engine::set_max_array_size (see [maximum size of arrays].

Built-in Functions

The following methods (mostly defined in the [BasicArrayPackage][packages] but excluded if using a [raw Engine]) operate on arrays:

Function Parameter(s) Description
push element to insert inserts an element at the end
append array to append concatenates the second array to the end of the first
+= operator 1) array
2) element to insert (not another array)
inserts an element at the end
+= 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
insert 1) element to insert
2) position, beginning if < 0, end if > length
inserts an element at a certain index
pop none removes the last element and returns it ([()] if empty)
shift none removes the first element and returns it ([()] if empty)
extract 1) start position, beginning if < 0, end if > length,
2) (optional) number of items to extract, none if < 0
extracts a portion of the array into a new array
remove index removes an element at a particular index and returns it ([()] if the index is not valid)
reverse none reverses the array
len method and property none returns the number of elements
pad 1) target length
2) element to pad
pads the array with an element to at least a specified length
clear none empties the array
truncate target length cuts off the array at exactly a specified length (discarding all subsequent elements)
chop target length cuts off the head of the array, leaving the tail at exactly a specified length
splice 1) start position, beginning 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)
filter [function pointer] to predicate (usually a [closure]) constructs a new array with all items that returns true when called with the predicate function:
1st parameter: array item,
2nd parameter: (optional) offset index
map [function pointer] to conversion function (usually a [closure]) constructs a new array with all items mapped to the result of applying the conversion function:
1st parameter: array item,
2nd parameter: (optional) offset index
reduce 1) [function pointer] to accumulator function (usually a [closure]),
2) (optional) [function pointer] to function (usually a [closure]) that provides the initial value
reduces the array into a single value via the accumulator function:
1st parameter: accumulated value ([()] initially),
2nd parameter: array item,
3rd parameter: (optional) offset index
reduce_rev 1) [function pointer] to accumulator function (usually a [closure]),
2) (optional) [function pointer] to function (usually a [closure]) that provides the initial value
reduces the array (in reverse order) into a single value via the accumulator function:
1st parameter: accumulated value ([()] initially),
2nd parameter: array item,
3rd parameter: (optional) offset index
some [function pointer] to predicate (usually a [closure]) returns true if any item returns true when called with the predicate function:
1st parameter: array item,
2nd parameter: (optional) offset index
none [function pointer] to predicate (usually a [closure]) returns true if no item returns true when called with the predicate function:
1st parameter: array item,
2nd parameter: (optional) offset index
all [function pointer] to predicate (usually a [closure]) returns true if all items return true when called with the predicate function:
1st parameter: array item,
2nd parameter: (optional) offset index
sort [function pointer] to a comparison function (usually a [closure]) sorts the array with a comparison function:
1st parameter: first item,
2nd parameter: second item,
return value: INT < 0 if first < second, > 0 if first > second, 0 if first == second

Use Custom Types With Arrays

To use a [custom type] with arrays, a number of array functions need to be manually implemented, in particular push, insert, pad and the += operator. In addition, the == operator must be implemented for the [custom type] in order to support the in operator which uses == 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 '==' operator (which users can override)
                            // to check if the target item exists in the array

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

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;

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]

// Use a closure to provide the initial value
a.reduce(|sum, v| sum + v, || 0) == 264;

// Detect the initial value of '()'
a.reduce(
    |sum, v| if sum.type_of() == "()" { v } else { sum + v }
) == 264;

// Detect the initial value via index
a.reduce(|sum, v, i|
    if i == 0 { v } else { sum + v }
) == 264;

// Use a closure to provide the initial value
a.reduce_rev(|sum, v| sum + v, || 0) == 264;

// Detect the initial value of '()'
a.reduce_rev(
    |sum, v| if sum.type_of() == "()" { v } else { sum + v }
) == 264;

// Detect the initial value via index
a.reduce_rev(|sum, v, i|
    if i == 2 { v } else { sum + v }
) == 264;

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

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| x - y);       // a == [1, 2, 3, 42, 99]