This page gives an overview of the use of lists of all types, including:
basic lists (of class BasicList),
visible lists (of class VisibleList),
lists (of class List),
sequences (of class Sequence),
arrays (of class Array), angle bar lists (of class AngleBarList), and
mutable lists (of class MutableList).
The sections of the overview are, in order:
Creating lists; kinds of lists.
Elements and indexing.
Nested lists.
Ranges and repetitions.
Manipulating lists and sequences.
Mapping over lists.
Conditional expressions; selecting elements matching a criterion.
Links to individual documentation pages for the functions described in this article are collected in an alphabetized list at the very end of the page.
Creating lists; kinds of lists.
To create a list, use curly braces around a comma-separated series of elements.
|
Sequences are created and displayed using parentheses instead of braces.
|
Sequences are implemented in a more efficient way than lists, since a sequence is created every time a function is called with more than one argument. On the other hand, parentheses are also used for grouping algebraic expressions. This complicates some tasks, such as creating a sequence of length 1.
|
|
|
The functions toList and toSequence, which convert between lists and sequences, may be useful here.
|
Lists can be used as vectors, provided their elements are the sorts of things that can be added and multiplied.
|
An array is another type of list, created and displayed using square brackets. Unlike lists and sequences, arrays can't be used as vectors. Their main use is notational; for example, they appear in the construction of polynomial rings.
|
|
An angle bar list is another type of list, created and displayed using angle bars. They are used in much the same way as arrays are.
|
|
Lists, sequences, and arrays are the three examples of what we call visible lists, which constitute the class VisibleList. Many functions are defined to act uniformly on visible lists. There is a type of list more general than a visible list, which we call a BasicList. Basic lists are a secure choice for defining new datatypes, since the many functions that act on visible lists do not act on basic lists. Here we illustrate how to create a new type of basic list, in this case called Container.
|
|
We can then declare a new method for the operator ++ that will join two Containers:
|
|
Basic lists are normally immutable; that is, no element can be replaced, added, or removed. (Functions like append, and the many others described in the Manipulating lists and sequences section, will return a new list in Macaulay2, as a general rule, rather than modify the existing list.)
However, there is a certain type of basic list, called a mutable list (of class MutableList), whose elements can be changed. This allows the possibility of creating circular structures that would cause a print routine to go into an infinite loop. To avoid such infinite loops, the contents of mutable lists are not printed. Instead, use peek to display the elements in a controlled way.
|
|
|
|
|
Because the contents of mutable lists are not printed, they can be used as containers for big things one doesn't want to print. Although any mutable list can be used in this way, there is a a special type of mutable list called a Bag, which is designed for this purpose. When printed, the bag displays only a little information about its contents.
|
|
|
The hierarchy of types mentioned above is summarized here using showStructure:
|
Elements and indexing.
We retrieve the length of a list with the operator # or with the function length.
|
|
|
The expression $L\#n$ returns the $n$th element of $L$. The elements are numbered consecutively starting with 0. Alternatively, they are numbered consecutively ending with -1.
|
|
|
The _ operator is similar to #, except that it can also take a list or range of indices. However, it may only be used with visible lists.
|
|
|
|
Omitting an element of a list causes the symbol null to be inserted in its place. When the value of an expression is null, like when we ask for A#2 in the next example, the output line doesn't appear at all.
|
|
|
Ranges and repetitions.
The operator .. can be used to create sequences of numbers, sequences of subscripted variables, and so on.
|
The operator ZZ : Thing creates a sequence by replicating an element a given number of times.
|
Replicating something once is another way to create a sequence of length 1, which cannot be entered by simply typing parentheses.
|
Both .. and : produce sequences, and may not behave as expected with respect to nesting. For instance, to create the list \{3, 4, 5, 6, 9, 12, 12, 12\}, the following command will not work:
|
Instead, we get a list of length 3, some of whose elements are sequences. This is easily resolved with splice.
|
However, many operators and functions will automatically splice lists for you. Two examples are the array of variables defining a polynomial ring, and the indices passed to the _ operator.
|
|
Nested lists.
When the elements of a list are themselves lists, we call it a nested list.
|
|
|
One level of nesting may be eliminated with flatten.
|
The function splice acts analogously on sequences, removing those pairs of parentheses that are one level inward.
|
To remove all layers of nesting at once, use deepSplice.
|
A table is a list whose elements are lists all of the same length. The inner lists are regarded as rows when the table is displayed as a two-dimensional array with MatrixExpression.
|
|
|
The function table can be used to create a table (doubly nested list) from two lists and a function of two arguments. It applies the function consecutively to each element from the first list paired with each element from the second list, so the total number of evaluations of the function is the product of the lengths of the two lists.
|
The function pack(L, n) turns the list $L$ into a nested list, whose elements are lists containing the elements of $L$ taken $n$ at a time.
|
On the other hand, mingle(L) takes the nested list $L = \{L_1, L_2, \ldots, L_n\}$ and combines the elements of the $L_i$ into a single list in the following way:
|
Manipulating lists and sequences.
Use append(L, x) to create a copy of $L$ with the element $x$ added to the end. Since lists are immutable in Macaulay2, $L$ itself is not changed, unless redefined.
|
|
|
|
Use prepend(x, L) to create a copy of $L$ with $x$ added to the beginning of the list. Notice the order of arguments is the opposite of append!
|
Use insert(n, x, L) to specify that the element $x$ should be added to the list $L$ at position $n$.
|
Use switch(m, n, L) to switch the elements of $L$ in indices $m$ and $n$.
|
The function delete removes elements that have a particular value, NOT a particular index.
|
To remove the element at index $n$, use the command drop(L, \{n,n\}).
|
You can also use drop to remove a specified number of elements from the beginning or end of $L$.
|
|
On the other hand, use take to specify the number of elements to keep, or a range of indices to keep:
|
|
Use between(x, L) to insert the element $x$ between every two elements of $L$.
|
Useful commands for reordering lists are reverse (reverse the current order), sort (put elements in ascending order), and rsort (put elements in descending order).
|
|
|
|
Use unique to remove duplicates from a list or sequence.
|
|
|
Mapping over lists.
In programming, loops that operate on consecutive elements of a list are common, so we offer various ways to apply functions to each of the elements of a list, along with various ways to treat the returned values.
The most basic operation is provided by scan, which applies a function consecutively to each element of a list, discarding the values returned.
|
The keyword break can be used to terminate the scan prematurely, and optionally to specify a return value for the expression. Here we use it to locate the first even number in a list.
|
|
This operation is so common that we offer two shorthand notations for it, one with the function on the right and one with the function on the left.
|
|
The associativity of these operators during parsing is set up so the following code works as one would wish.
|
|
|
The function apply can also be used with two lists of the same length, in which case it will apply the function consecutively to corresponding elements of the two lists.
|
The function applyTable can be used to apply a function to each element of a table.
|
The functions fold and accumulate provide various ways to iteratively apply a function of two arguments to the elements of a list. One of the arguments is the next element from the list, and the other argument is the value returned by the previous application of the function. As an example, suppose we want to convert the list \{7,3,5,4,2\} of digits into the corresponding number 73542. The formula (((7*10+3)*10+5)*10+4)+2 is a fast way to do it that doesn't involve computing high powers of 10 separately. We can do this with fold and the following code.
|
Using accumulate returns all the intermediate values of this iterative calculation along with the final result.
|
Conditional expressions; selecting elements matching a criterion.
Use select to select those elements from a list that satisfy some condition.
|
|
An optional first argument of an integer $n$ specifies to select no more than $n$ matching elements.
|
Use positions to select the indices of elements satisfying the condition.
|
The singular position returns only the first (or last, by specifying Reverse => true) matching index.
|
|
Use number to count how many elements satisfy the condition.
|
Use max and min to find the maximum or minimum of the list. The functions maxPosition and minPosition give the index of the maximum/minimum. Note that max and min work with many Macaulay2 types besides numbers, for instance elements of a polynomial ring with respect to a monomial order.
|
|
|
|
|
We may use any to tell whether there is at least one element of a list satisfying a condition, and all to tell whether all elements satisfy it.
|
|
The source of this document is in Macaulay2Doc/ov_lists.m2:535:0.