Skip to main content

Collections

In the Compute Engine, collections group together multiple elements into one unit. Each element in a collection is a Boxed Expression.

Introduction

Collections are immutable. They cannot be modified. Operations on collections produce new collections.

There are several types of collections in the Compute Engine:

  • Lists: ordered collections of elements, which are also used to represent vectors and matrices. Elements in a list are accessed by their index, which starts at 1.
  • Sets: unordered collections of unique elements. The elements in a set are not accessed by index, they are enumerated. A set can contain an infinite number of elements.
  • Tuples: ordered collections of elements, but with a fixed number of elements that have a specific type and an optional name.
  • Records: unordered collections of key-value pairs.
  • Ranges and Linear Spaces (linspaces): ordered sequences of numbers (integers and reals, respectively) with a specified start, end and step size.

Operations on Collections

Operations creating new collections:

Operations on ordered and unordered collections:

  • Length, IsEmpty: check the size of a collection.
  • Filter, Map, Reduce: apply a function to each element of a collection.
  • Join, Zip: combine multiple collections into one.
  • Tally: count the number of occurrences of each element in a collection.

Operations on ordered collections:

Indexing Collections

Ordered collections (lists, tuples, ranges and linspaces) are indexed starting from 1. Negative indexes count from the end of the collection. For example, -1 is the last element, -2 is the second to last element, etc.

["At", ["List", 2, 5, 7, 11], -2]
// ➔ 7

["At", ["Range", 2, 10], -1]
// ➔ ["List", 10]

Creating Collections

This section contains functions that create new collections from some values.

List

List: (...element:any) -> list

A List is an ordered, indexable collection of elements. An element in a list may be repeated.

\lbrack 42, 3.14, x, y \rbrack
$$$\lbrack 42, 3.14, x, y \rbrack$$
["List", 42, 3.14, "x", "y"]

The visual presentation of a List expression can be customized using the Delimiter function.

ce.box(["List", 5, 2, 10, 18]).latex;
// ➔ "\lbrack 5, 2, 10, 18 \rbrack"

ce.box(["Delimiter", ["List", 5, 2, 10, 18], "<;>"]).latex;
// ➔ "\langle5; 2; 10; 18\rangle"

A vector is represented as a List of numbers.

\lbrack 1, 2, 3 \rbrack
$$$\lbrack 1, 2, 3 \rbrack$$
["List", 1, 2, 3]

A matrix is represented using a List of rows of numbers, where each row is a List of numbers.

\lbrack \lbrack 1, 2, 3 \rbrack, \lbrack 4, 5, 6 \rbrack, \lbrack 7, 8, 9 \rbrack \rbrack
$$$\lbrack \lbrack 1, 2, 3 \rbrack, \lbrack 4, 5, 6 \rbrack, \lbrack 7, 8, 9 \rbrack \rbrack$$
["List", 
["List", 1, 2, 3],
["List", 4, 5, 6],
["List", 7, 8, 9]
]

In LaTeX, lists of lists can also be represented using a ; separator:

\lbrack 1, 2, 3 ; 4, 5, 6 ; 7, 8, 9 \rbrack
$$$\lbrack 1, 2, 3 ; 4, 5, 6 ; 7, 8, 9 \rbrack$$

And matrices can be represented using LaTeX environments with the \begin{} and \end{} commands:

\begin{pmatrix} 1 & 2 & 3 \\ 4 & 5 & 6 \\ 7 & 8 & 9 \end{pmatrix}
$$$\begin{pmatrix} 1 & 2 & 3 \\ 4 & 5 & 6 \\ 7 & 8 & 9 \end{pmatrix}$$
MathJSONLaTeX
["List", "x", "y", 7, 11]\lbrack x, y, 7, 11\rbrack
["List", "x", "Nothing", "y"]\lbrack x,,y\rbrack

Range

Range: (upper:integer) -> collection<integer>

Range: (lower:integer, upper:integer) -> collection<integer>

Range: (lower:integer, upper:integer, step:integer) -> collection<integer>

A sequence of numbers, starting with lower, ending with upper, and incrementing by step.

If the step is not specified, it is assumed to be 1.

["Range", 3, 9]
// ➔ ["List", 3, 4, 5, 6, 7, 8, 9]

["Range", 1, 10, 2]
// ➔ ["List", 1, 3, 5, 7, 9]

If there is a single argument, it is assumed to be the upper bound, and the lower bound is assumed to be 1.

["Range", 7]
// ➔ ["List", 1, 2, 3, 4, 5, 6, 7]

If the lower bound is greater than the upper bound, the step must be negative.

["Range", 10, 1, -1]
// ➔ ["List", 10, 9, 8, 7, 6, 5, 4, 3, 2, 1]

Linspace

Linspace: (upper:real) -> collection<real>

Linspace: (lower:real, upper:real) -> collection<real>

Linspace: (lower:real, upper:real, count:integer) -> collection<real>

Short for "linearly spaced", from the MATLAB function of the same name.

A sequence of numbers evenly spaced between lower and upper. Similar to Range but the number of elements in the collection is specified with count instead of a step value.

If the count is not specified, it is assumed to be 50.

If there is a single argument, it is assumed to be the upper bound, and the lower bound is assumed to be 1.

["Linspace", 3, 10]
// ➔ ["List", 3, 3.142857142857143, 3.2857142857142856,
// 3.4285714285714284, 3.571428571428571, 3.714285714285714,
// 3.857142857142857, 4, 4.142857142857143, 4.285714285714286,
// 4.428571428571429, 4.571428571428571, 4.714285714285714,
// 4.857142857142857, 5, 5.142857142857143, 5.285714285714286,
// 5.428571428571429, 5.571428571428571, 5.714285714285714,
// 5.857142857142857, 6, 6.142857142857143, 6.285714285714286,
// 6.428571428571429, 6.571428571428571, 6.714285714285714,
// 6.857142857142857, 7, 7.142857142857143, 7.285714285714286,
// 7.428571428571429, 7.571428571428571, 7.714285714285714,
// 7.8979591836734695, 8.061224489795919, 8.224489795918368,
// 8.387755102040817, 8.551020408163266, 8.714285714285714,
// 8.877551020408163, 9.040816326530612, 9.204081632653061,
// 9.36734693877551, 9.53061224489796, 9.693877551020408,
// 9.857142857142858, 10]

["Linspace", 2]
// ➔ ["List", 1, 1.1428571428571428, 1.2857142857142858,
// 1.4285714285714286, 1.5714285714285714,
// 1.7142857142857142, 1.8571428571428572, 2]

["Linspace", 1, 10, 5]
// ➔ ["List", 1, 3.25, 5.5, 7.75, 10]

["Linspace", 10, 1, 10]
// ➔ ["List", 10, 9.11111111111111, 8.222222222222221,
// 7.333333333333333, 6.444444444444445,
// 5.555555555555555, 4.666666666666666, 3.7777777777777777,
// 2.888888888888889, 2]

Set

Set: (...elements:any) -> set

An unordered collection of unique elements.

\lbrace 12, 15, 17 \rbrace
$$$\lbrace 12, 15, 17 \rbrace$$
["Set", 12, 15, 17]

Fill

Fill: (dimensions, value:any) -> list

Fill: (dimensions, f:function) -> list

Create a list of the specified dimensions.

If a value is provided, the elements of the list are all set to that value.

If a function is provided, the elements of the list are computed by applying the function to the index of the element.

If dimensions is a number, a list of that length is created.

["Fill", 3, 0]
// ➔ ["List", 0, 0, 0]

If dimension is a tuple, a matrix of the specified dimensions is created.

["Fill", ["Tuple", 2, 3], 0]
// ➔ ["List", ["List", 0, 0, 0], ["List", 0, 0, 0]]

If a function is specified, it is applied to the index of the element to compute the value of the element.

["Fill", ["Tuple", 2, 3], ["Function", ["Add", "i", "j"], "i", "j"]]
// ➔ ["List", ["List", 0, 1, 2], ["List", 1, 2, 3]]

Repeat

Repeat: (value: any) -> list

An infinite list of the same element.

Repeat: (value: any, count: integer?) -> list

A list of the same element repeated count times.

["Repeat", 42, 5]

Note: ["Repeat", n] is equivalent to ["Cycle", ["List", n]].

Cycle: (seed:collection) -> list

A collection that repeats the elements of the seed collection. The seed collection must be finite.

["Cycle", ["List", 5, 7, 2]]
// ➔ ["List", 5, 7, 2, 5, 7, 2, 5, 7, ...]

["Cycle", ["Range", 3]]
// ➔ ["List", 1, 2, 3, 1, 2, 3, 1, 2, ...]

Use Take to get a finite number of elements.

["Take", ["Cycle", ["List", 5, 7, 2]], 5]
// ➔ ["List", 5, 7, 2, 5, 7]

Iterate

Iterate: (f:function) -> list

Iterate: (f:function, initial:any) -> list

An infinite collection of the results of applying f to the initial value.

If the initial value is not specified, it is assumed to be 0

["Iterate", ["Function", ["Multiply", "_", 2]], 1]


// ➔ ["List", 1, 2, 4, 8, 16, ...]

Use Take to get a finite number of elements.

["Take", ["Iterate", ["Function", ["Add", "_", 2]], 7], 5]
// ➔ ["List", 7, 9, 11, 13, 15]

Operating On Collections

The section contains functions whose argument is a collection, but whose return value is not a collection.

At

At: (collection, index)

At: (collection, index1, index2, ...)

Returns the element at the specified index.

If the collection is nested, the indexes are applied in order.

["At", ["List", 5, 2, 10, 18], 2]
// ➔ 10

["At", ["List", 5, 2, 10, 18], -2]
// ➔ 10

["At", ["List", ["List", 1, 2], ["List", 3, 4]], 2, 1]
// ➔ 3

Filter

Filter: (collection, function)

Returns a collection where function is applied to each element of the collection. Only the elements for which the function returns "True" are kept.

["Filter", ["List", 5, 2, 10, 18], ["Function", ["Less", "_", 10]]]
// ➔ ["List", 5, 2]

First

First: (collection)

Return the first element of the collection.

It's equivalent to ["Take", _collection_, 1].

["First", ["List", 5, 2, 10, 18]]
// ➔ 5

["First", ["Tuple", "x", "y"]]
// ➔ "x"

Last

Last: (collection)

Return the last element of the collection.

["Last", ["List", 5, 2, 10, 18]]
// ➔ 18

Last: (collection, n)

Return the last n elements of the collection.

["Last", ["List", 5, 2, 10, 18], 2]
// ➔ ["List", 10, 18]

Length

Length: (collection)

Returns the number of elements in the collection.

When the collection is a matrix (list of lists), Length returns the number of rows.

["Length", ["List", 5, 2, 10, 18]]
// ➔ 4

When the collection is a string, Length returns the number of characters in the string.

["Length", { "str": "Hello" }]
// ➔ 5

IsEmpty

IsEmpty: (collection)

Returns the symbol True if the collection is empty.

["IsEmpty", ["List", 5, 2, 10, 18]]
// ➔ "False"

["IsEmpty", ["List"]]
// ➔ "True"

["IsEmpty", "x"]
// ➔ "True"


["IsEmpty", {str: "Hello"]
// ➔ "False"

Map

Map: (xs:collection, f:function) -> collection

Returns a collection where f is applied to each element of xs.

["Map", ["List", 5, 2, 10, 18], ["Function", ["Add", "x", 1], "x"]]
// ➔ ["List", 6, 3, 11, 19]
["Map", ["List", 5, 2, 10, 18], ["Multiply", "_", 2]]
// ➔ ["List", 10, 4, 20, 36]

Reduce

Reduce: (xs:collection, fn:function, initial:value?) -> value

Returns a value by applying the reducing function fn to each element of the collection.

Reduce performs a left fold operation: the reducing function is applied to the first two elements, then to the result of the previous application and the next element, etc...

When an initial value is provided, the reducing function is applied to the initial value and the first element of the collection, then to the result of the previous application and the next element, etc...

[
"Reduce",
["List", 5, 2, 10, 18],
["Function", ["Add", "_1", "_2"]],
]
// ➔ 35

The name of a function can be used as a shorthand for a function that takes two arguments.

["Reduce", ["List", 5, 2, 10, 18], "Add"]
// ➔ 35

Ordering: (collection)

Ordering: (collection, order-function)

Return the indexes of the collection in sorted order.

["Ordering", ["List", 5, 2, 10, 18]]
// ➔ ["List", 2, 1, 3, 4]

To get the values in sorted order, use Extract:

["Assign", "l", ["List", 5, 2, 10, 18]]
["Extract", "l", ["Ordering", "l"]]
// ➔ ["List", 2, 5, 10, 18]

// Same as Sort:
["Sort", "l"]
// ➔ ["List", 2, 5, 10, 18]

Second

Second: (collection)

Return the second element of the collection.

["Second", ["Tuple", "x", "y"]]
// ➔ "y"

Tally

Tally: (xs:collection) -> tuple<elements:list, counts:list>

Evaluate to a tuple of two lists:

  • The first list contains the unique elements of the collection.
  • The second list contains the number of times each element appears in the collection.
["Tally", ["List", 5, 2, 10, 18, 5, 2, 5]]
// ➔ ["Tuple", ["List", 5, 2, 10, 18], ["List", 3, 2, 1, 1]]

Zip

Zip: (collection-1, collection-2, ...)

Returns a collection of tuples where the first element of each tuple is the first element of the first collection, the second element of each tuple is the second element of the second collection, etc.

The length of the resulting collection is the length of the shortest collection.

["Zip", ["List", 1, 2, 3], ["List", 4, 5, 6]]
// ➔ ["List", ["Tuple", 1, 4], ["Tuple", 2, 5], ["Tuple", 3, 6]]

Transforming Collections

This section contains functions whose argument is a collection and which return a collection made of a subset of the elements of the input.

Collections are immutable. These functions do not modify the input collection, but return a new collection.

Drop

Drop: (xs:collection, n:integer) -> collection

Return a list without the first n elements.

If n is negative, it returns a list without the last n elements.

["Drop", ["List", 5, 2, 10, 18], 2]
// ➔ ["List", 10, 18]

["Drop", ["List", 5, 2], -2]
// ➔ ["List", 5, 2]

See Take for a function that returns the first n elements.

Exclude

Exclude: (xs:collection,, index:integer) -> collection

Exclude: (xs:collection, indexes:collection<integer>) -> collection

Exclude is the opposite of Extract. It returns a list of the elements that are not at the specified index.

The order of the elements is preserved.

["Exclude", ["List", 5, 2, 10, 18], 2]
// ➔ ["List", 5, 10, 18]

["Exclude", ["List", 5, 2, 10, 18], -2, 1]
// ➔ ["List", 2, 18]

When indexes is a list, it is used to specify the indexes of the elements to be dropped.

["Exclude", ["List", 5, 2, 10, 18], ["List", 2, 3]]
// ➔ ["List", 5, 2]

["Exclude", ["List", 5, 2, 10, 18], ["List", -2, 1]]
// ➔ ["List", 2, 18]

An index may be repeated, but the corresponding element will only be dropped once.

["Exclude", ["List", 5, 2, 10, 18], ["List", 3, 3, 1]]
// ➔ ["List", 2, 18]

Extract

Extract: (collection, index)

Extract: (collection, index1, index2)

Extract: (collection, range)

Returns a list of the elements at the specified indexes.

Extract is a flexible function that can be used to extract a single element, a range of elements, or a list of elements.

Extract always return a list, even if the result is a single element. If no elements match, an empty list is returned.

["Extract", ["List", 5, 2, 10, 18], 2]
// ➔ ["List", 10]

["Extract", ["List", 5, 2, 10, 18], -2, 1]
// ➔ ["List", 10, 5]


["Extract", ["List", 5, 2, 10, 18], 17]
// ➔ ["List"]

When using a range, it is specified as a Range expression.

// Elements 2 to 3
["Extract", ["List", 5, 2, 10, 18], ["Range", 2, 4]]
// ➔ ["List", 2, 10, 18]

// From start to end, every other element
["Extract", ["List", 5, 2, 10, 18], ["Range", 1, -1, 2]]
// ➔ ["List", 5, 10]

The elements are returned in the order in which they're specified. Using negative indexes (or ranges) reverses the order of the elements.

// From last to first = reverse
["Extract", ["List", 5, 2, 10, 18], ["Range", -1, 1]]
// ➔ ["List", 18, 10, 2, 5]

// From last to first = reverse
["Extract", ""desserts"", ["Range", -1, 1]]
// ➔ ""stressed""

An index can be repeated to extract the same element multiple times.

["Extract", ["List", 5, 2, 10, 18], 3, 3, 1]
// ➔ ["List", 10, 10, 5]

Join

Join: (...collections:collection) -> list

Join: (...sets:set) -> set

If the collections are of different types, the result is a List containing the elements of the first collection followed by the elements of the second collection.

["Join", ["List", 5, 2, 10, 18], ["List", 1, 2, 3]]
// ➔ ["List", 5, 2, 10, 18, 1, 2, 3]

If the collections are all sets , the result is a Set of the elements of the collections.

["Join", ["Set", 5, 2, 10, 18], ["Set", 1, 2, 3]]
// ➔ ["Set", 5, 2, 10, 18, 1, 3]

Most

Most: (collection)

Return everything but the last element of the collection.

It's equivalent to ["Drop", _collection_, -1].

["Most", ["List", 5, 2, 10, 18]]
// ➔ ["List", 5, 2, 10]

Rest

Rest: (collection)

Return everything but the first element of the collection.

It's equivalent to ["Drop", _collection_, 1].

["Rest", ["List", 5, 2, 10, 18]]
// ➔ ["List", 2, 10, 18]

Reverse

Reverse: (collection)

Return the collection in reverse order.

["Reverse", ["List", 5, 2, 10, 18]]
// ➔ ["List", 18, 10, 2, 5]

It's equivalent to ["Extract", _collection_, ["Tuple", -1, 1]].

RotateLeft

RotateLeft: (collection, count)

Returns a collection where the elements are rotated to the left by the specified count.

["RotateLeft", ["List", 5, 2, 10, 18], 2]
// ➔ ["List", 10, 18, 5, 2]

RotateRight

RotateRight: (collection, count)

Returns a collection where the elements are rotated to the right by the specified count.

["RotateRight", ["List", 5, 2, 10, 18], 2]
// ➔ ["List", 10, 18, 5, 2]

Shuffle

Shuffle: (xs:collection) -> list

Return the collection in random order.

["Shuffle", ["List", 5, 2, 10, 18]]
// ➔ ["List", 10, 18, 5, 5]

Sort

Sort: (collection)

Sort: (collection, order-function)

Return the collection in sorted order.

["Sort", ["List", 5, 2, 10, 18]]
// ➔ ["List", 2, 5, 10, 18]

Take

Take: (xs:collection, n:integer) -> collection

Return a list of the first n elements of xs. The collection xs must be ordered.

If n is negative, it returns the last n elements.

["Take", ["List", 5, 2, 10, 18], 2]
// ➔ ["List", 5, 2]

["Take", ["List", 5, 2, 10, 18], -2]
// ➔ ["List", 18, 10]

See Drop for a function that returns everything but the first n elements.

Unique

Unique: (xs: collection) -> collection

Returns a list of the elements in xs without duplicates.

This is equivalent to the first element of the result of Tally: ["First", ["Tally", xs]].

["Unique", ["List", 5, 2, 10, 18, 5, 2, 5]]
// ➔ ["List", 5, 2, 10, 18]