6.13.1 Slices

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.