A binary operation applied between two arrays of numbers yields an array
of results in Yorick – the operation is performed once for each
corresponding pair of elements of the operands. Hence, if `rho` and
`vol` are each four-by-three arrays, the expression `rho*vol`
will be a four-by-three array of products, starting with
`rho(1,1)*vol(1,1)`.

This extension of binary operations to array operands is not always
appropriate. Instead of operating on the corresponding elements of
arrays of the same shape, you may want to perform the operation between
all pairs of elements. The most common example is the outer product
of two vectors `x` and `y`:

outer= x*y(-,); |

Here, if `x` were a four element vector, and `y` were a three
element vector, `outer` would be the four-by-three array
`[[x(1)*y(1), x(2)*y(1), x(3)*y(1), x(4)*y(1)], [x(1)*y(2),
x(2)*y(2), x(3)*y(2), x(4)*y(2)], [x(1)*y(3), x(2)*y(3), x(3)*y(3),
x(4)*y(3)]]`.

In Yorick, this type of multiplication is still commutative. That is,
`x*y(-,)` is the same as `y(-,)*x`. To produce the three-by-four
transpose of the array `outer`, you would write `x(-,)*y`.

I call the `-` sign, when used as an index, a pseudo-index because
it actually inserts an additional dimension into the result array which
was not present in the array being indexed. By itself, the expression
`y(-,)` is a one-by-three array (with the same three values as the
three element vector `y`). You may insert as many pseudo-indices
into a list of subscripts as you like, at any location you like relative
to the actual dimensions of the array you are indexing. Hence,
`outer(-,-,,-,)` would be a one-by-one-by-four-by-one-by-three array.

By default, a pseudo-index produces a result dimension of length one.
However, by appending an index range to the `-` sign, separated by
a colon, you can produce a new dimension of any convenient length:

x = span(-10, 10, 100)(,-:1:50); y = span(-5, 5, 50)(-:1:100,); gauss2d = exp(-0.5*(x^2+y^2))/(2.0*pi); |

computes a normalized 2-D Gaussian function on a 100-by-50 rectangular
grid of points in the xy-plane. The pseudo-index `-:1:50` has 50
elements, and `-:1:100` has 100. For a pseudo-index of non-unit
length, the values along the actual dimensions are simply copied, so
that `span(-10, 10, 100)(,-:1:50)` is a 100-by-50 array consisting
of 50 copies of `span(-10, 10, 100)`.

If only the result `gauss2d` were required, a single default
pseudo-index would have sufficed:

gauss2d = exp(-0.5*( span(-10,10,100)^2 + span(-5,5,50)(-,)^2 )) / (2.0*pi); |

However, the rectangular grid of points (`x`,`y`) is often
required – as input to plotting routines for example.