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:
- List, Range, Linspace, Set: create a new collection from some values.
- Fill, Repeat, Cycle, Iterate: create a new collection from a function or a value.
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:
- At, First, Second, Last: access a specific element of a collection.
- Take, Drop, Most, Rest: access a subset of a collection.
- IndexOf: find the index of an element in a collection.
- Extract, Exclude: access a collection of elements at specific indexes.
- Sort, Shuffle, Reverse: reorder a collection.
- Unique: remove duplicates from a collection.
- RotateLeft, RotateRight: rotate a collection to the left or right.
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: (...element:any) -> list
A List
is an ordered, indexable collection of elements. An element in
a list may be repeated.
["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.
["List", 1, 2, 3]
A matrix is represented using a List
of rows of numbers, where each row is
a List
of numbers.
["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:
And matrices can be represented using LaTeX environments with the \begin{}
and \end{}
commands:
MathJSON | LaTeX |
---|---|
["List", "x", "y", 7, 11] | \lbrack x, y, 7, 11\rbrack |
["List", "x", "Nothing", "y"] | \lbrack x,,y\rbrack |
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: (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: (...elements:any) -> set
An unordered collection of unique elements.
["Set", 12, 15, 17]
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: (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: (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: (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: (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: (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: (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: (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: (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: (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: (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: (collection)
Return the second element of the collection.
["Second", ["Tuple", "x", "y"]]
// ➔ "y"
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: (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: (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: (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: (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: (...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: (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: (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: (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: (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: (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: (xs:collection) -> list
Return the collection in random order.
["Shuffle", ["List", 5, 2, 10, 18]]
// ➔ ["List", 10, 18, 5, 5]
Sort: (collection)
Sort: (collection, order-function)
Return the collection in sorted order.
["Sort", ["List", 5, 2, 10, 18]]
// ➔ ["List", 2, 5, 10, 18]
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: (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]