Many Yorick functions must work on arrays with an unknown number of dimensions. Consider a filter response function, which takes as input a spectrum (brightness as a function of photon energy), and returns the response of a detector. Such a function could be passed a spectrum and return a scalar value. Or, it might be passed a two dimensional array of spectra for each of a list of rays, and be expected to return the corresponding list of responses. Or a three dimensional array of spectra at each pixel of a two dimensional image, returning a two dimensional array of response values.
In order to write such a function, you need a way to say, “and all other indices this array might have”. Yorick’s rubber-index, .., stands for zero or more actual indices of the array being indexed. Any indices preceding a rubber-index are “left justified”, and any following it are “right justified”. Using this syntax, you can easily index an array, as long as you know that the dimension (or dimensions) you are interested in will always be first, or last – even if you don’t know how many spectator dimensions might be present in addition to the one your routine processes.
Thus, as long as the spectral dimension is always the final dimension of the input brightness array,
brightness(..,i) |
will always place the i index in the spectral dimension, whether brightness itself is a 1-D, 2-D, or 3-D array.
Similarly, x(i,..) selects a value of the first index of x, leaving intact all following dimensions, if any. Constructions such as x(i,j,..,k,l) are also legal, albeit rarely necessary.
A second form of rubber-index collapses zero or more dimensions into a single index. The length of the collapsed dimension will be the product of the lengths of all of the dimensions it replaces (or 1, if it replaces zero dimensions). The symbol for this type of rubber index is an asterisk *. For example, if x were a five-by-three-by-four-by-two array, then x(*) would be a 1-D array of 120 elements, while x(,*,) would be a five-by-twelve-by-two array.
If the last actual index in a subscripted array is nil, and if this index does not correspond to the final actual dimension of the array, Yorick will append a .. rubber-index to the end of the subscript list. Hence, in the previous example, x() is equivalent to x(,..), which is equivalent to x(..), which is equivalent to simply x. This rule is the only rogue in Yorick’s array subscripting stable, and I am mightily tempted to remove it on grounds of linguistic purity. When you mean, “and any other dimensions which might be present,” use the .. rubber-index, not a nil index. Use a trailing nil index only when you mean, “and the single remaining dimension (which I know is present).”