Collections

Introduction

In the Compute Engine, collections are used to represent data structures. They group together multiple elements into one unit. Each element in a collection is a Boxed Expression.

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

A ["List"] expression can represent an heterogeneous collection of elements.

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

List of numbers can be used to represent vectors.

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

A matrix is represented using a List of 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]]

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 matrixes can be represented using LaTeX environments:

\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} \]

Another common collection is the Range which is used to represent a sequence of numbers from a lower bound to an upper bound. Both lower and upper bounds are included in the range.

\lbrack 1..10 \rbrack
\[ \lbrack 1..10 \rbrack \]
["Range", 1, 10]

Collections operations such as IsEmpty, Extract, IndexOf can be applied to any collection types.

\lbrack 2, 5, 7 \rbrack_{2}
\[ \lbrack 2, 5, 7 \rbrack_{2} \]
["Extract", ["List", 2, 5, 7], 2]
// ➔ ["List", 5]
(2..10)_5
\[ (2..10)_5 \]
["Extract", ["Range", 2, 10], 5]
// ➔ ["List", 7]

Creating Collections

This section contains functions that return a collection, but whose arguments are not collections. They are used to create collections.

List

["List", x-1, …x-2]

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

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"
MathJSON LaTeX
["List", "x", "y", 7, 11] \( \lbrack x, y, 7, 11\rbrack \)
["List", "x", "Nothing", "y"] \( \lbrack x,y\rbrack \)

Range

["Range", upper]

["Range", lower, upper]

["Range", lower, upper, step]

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.

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

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

Linspace

["Linspace", upper]

["Linspace", lower, upper]

["Linspace", lower, upper, count]

Short for “linearly spaced”, from the (MATLAB function of the same name)[https://www.mathworks.com/help/matlab/ref/linspace.html].

A sequence of numbers. 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, 9]
// ➔ ["List", 3, 3.163265306122449, 3.326530612244898, 3.489795918367347, 3.653061224489796, 3.816326530612245, 3.979591836734694, 4.142857142857143, 4.3061224489795915, 4.469387755102041, 4.63265306122449, 4.795918367346939, 4.959183673469388, 5.122448979591837, 5.285714285714286, 5.448979591836735, 5.612244897959184, 5.775510204081633, 5.938775510204081, 6.1020408163265305, 6.26530612244898, 6.428571428571429, 6.591836734693878, 6.755102040816326, 6.918367346938775, 7.081632653061225, 7.244897959183673, 7.408163265306122, 7.571428571428571, 7.73469387755102, 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", 7]
// ➔ ["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", expr-1, …expr-2]

An unordered collection of unique elements.

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

Fill

["Fill", dimensions, value]

["Fill", dimensions, function]

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", expr]

An infinite collection of the same element.

["Repeat", 0]
// ➔ ["List", 0, 0, 0, ...]

Use Take to get a finite number of elements.

["Take", ["Repeat", 42], 3]
// ➔ ["List", 42, 42, 42]

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

Cycle

["Cycle", seed]

A collection that repeats the elements of the seed collection. The input 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", function]

["Iterate", function, initial]

An infinite collection of the results of applying function 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]

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.

Drop

["Drop", collection, n]

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]

Exclude

["Exclude", collection, index]

["Exclude", collection, index1, index2]

["Exclude", collection, range]

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

The elements are returned in the same order as they appear in the collection.

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

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

["Exclude", ["List", 5, 2, 10, 18], 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]

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"

Join

["Join", collection-1, collection-2, …]

Returns a collection that contains the elements of the first collection followed by the elements of the second collection.

All the collections should have the same head.

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

Take

["Take", collection, n]

Return a list of the first n elements of the collection.

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]

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]

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]

Second

["Second", collection]

Return the second element of the collection.

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

Shuffle

["Shuffle", collection]

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]

Unique

["Unique", collection]

Returns a list of the elements in collection without duplicates.

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

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

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.

There can be multiple indexes, up to the rank of the collection.

["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]

Fold

["Fold", collection, fn]

["Fold", collection, fn, initial]

Returns a collection where the reducing function fn is applied to each element of the collection.

Fold 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…

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

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

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

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", collection, function]

Returns a collection where function is applied to each element of the input collection.

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

Ordering

["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]

Tally

["Tally", collection]

Returns a tuples 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]]