Asymptote allows a section of an array to be addressed as a slice
using a Python-like syntax. If A
is an array, the expression
A[m:n]
returns a new array consisting of the elements of A
with
indices from m
up to but not including n
. For example,
int[] x={0,1,2,3,4,5,6,7,8,9}; int[] y=x[2:6]; // y={2,3,4,5}; int[] z=x[5:10]; // z={5,6,7,8,9};
If the left index is omitted, it is taken be 0
. If the right index is
omitted it is taken to be the length of the array. If both are omitted, the
slice then goes from the start of the array to the end, producing a non-cyclic
deep copy of the array. For example:
int[] x={0,1,2,3,4,5,6,7,8,9}; int[] y=x[:4]; // y={0,1,2,3} int[] z=x[5:]; // z={5,6,7,8,9} int[] w=x[:]; // w={0,1,2,3,4,5,6,7,8,9}, distinct from array x.
If A is a non-cyclic array, it is illegal to use negative values for either of the indices. If the indices exceed the length of the array, however, they are politely truncated to that length.
For cyclic arrays, the slice A[m:n]
still consists of the cells with
indices in the set [m
,n
), but now negative
values and values beyond the length of the array are allowed. The indices
simply wrap around. For example:
int[] x={0,1,2,3,4,5,6,7,8,9}; x.cyclic=true; int[] y=x[8:15]; // y={8,9,0,1,2,3,4}. int[] z=x[-5:5]; // z={5,6,7,8,9,0,1,2,3,4} int[] w=x[-3:17]; // w={7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6}
Notice that with cyclic arrays, it is possible to include the same element of the original array multiple times within a slice. Regardless of the original array, arrays produced by slices are always non-cyclic.
If the left and right indices of a slice are the same, the result is an empty array. If the array being sliced is empty, the result is an empty array. Any slice with a left index greater than its right index will yield an error.
Slices can also be assigned to, changing the value of the original array. If the array being assigned to the slice has a different length than the slice itself, elements will be inserted or removed from the array to accommodate it. For instance:
string[] toppings={"mayo", "salt", "ham", "lettuce"}; toppings[0:2]=new string[] {"mustard", "pepper"}; // Now toppings={"mustard", "pepper", "ham", "lettuce"} toppings[2:3]=new string[] {"turkey", "bacon" }; // Now toppings={"mustard", "pepper", "turkey", "bacon", "lettuce"} toppings[0:3]=new string[] {"tomato"}; // Now toppings={"tomato", "bacon", "lettuce"}
If an array is assigned to a slice of itself, a copy of the original array
is assigned to the slice. That is, code such as x[m:n]=x
is equivalent
to x[m:n]=copy(x)
. One can use the shorthand x[m:m]=y
to insert
the contents of the array y
into the array x
starting at the
location just before x[m]
.
For a cyclic array, a slice is bridging if it addresses cells up to the end of
the array and then continues on to address cells at the start of the array.
For instance, if A
is a cyclic array of length 10, A[8:12]
,
A[-3:1]
, and A[5:25]
are bridging slices whereas A[3:7]
,
A[7:10]
, A[-3:0]
and A[103:107]
are not. Bridging slices
can only be assigned to if the number of elements in the slice is exactly equal
to the number of elements we are assigning to it. Otherwise, there is no clear
way to decide which of the new entries should be A[0]
and an error is
reported. Non-bridging slices may be assigned an array of any length.
For a cyclic array A
an expression of the form
A[A.length:A.length]
is equivalent to the expression A[0:0]
and
so assigning to this slice will insert values at the start of the array.
A.append()
can be used to insert values at the end of the array.
It is illegal to assign to a slice of a cyclic array that repeats any of the cells.