Operators form a powerful extension to the repertoire of the language. They can be used to specify the way in which a function or functions are to be applied to data - they allow a function to be applied repeatedly and cumulatively over all the elements of a vector, matrix or multidimensional array.
They can be thought of as instructions to built-in and user-defined functions on how to carry out their operations. You can even define your own operators!
The operators available are:
Reduce and scan
When used with functions as their operand, slash and backslash are known as reduce and scan. Reduce and scan apply a single function to all the elements of an argument. For example, to add up a vector of arguments, you can either type:
22 + 93 + 4.6 + 10 + 3.3 132.9
+/22 93 4.6 10 3.3 132.9
+\22 93 4.6 10 3.3 22 115 119.6 129.6 132.9
from the results of:
22 (22+93) (115+4.6) (119.6+10) (129.6+3.3)
There are more examples of reduction and scan in the APLX Language Manual.
Compress and Expand
When used with one or more numbers as their operand, slash and backslash carry out operations known as compression and expansion.
Compress can be used to select all or part of an object, according to the value of the numbers forming its operand. For example, to select some characters from a vector:
1 0 1 1 0 1 / 'ABCDEF' ACDF
Conversely, expand will insert fill data into objects:
TAB ← 2 3⍴⍳6 TAB 1 2 3 4 5 6 1 0 1 0 1 \TAB 1 0 2 0 3 4 0 5 0 6
Columns are inserted in positions indicated by the
Outer and inner products
The product operators allow APL functions to be applied between all the elements in one argument and all the elements in another.
This is an important extension because previously functions have only applied to corresponding elements as in this example:
1 2 3 + 4 5 6 5 7 9
The outer product gives the result of applying the function to all combinations of the elements in the two arguments. For example, to find the outer product of the two arguments used in the last example:
1 2 3 ∘.+ 4 5 6 5 6 7 6 7 8 7 8 9
The first row is the result of adding the first element on the left to every element on the right, the second row is the result of adding the second element in the left to every element on the right and so on till all combinations are exhausted.
This example works out a matrix of powers:
1 2 3 4 ∘.*1 2 3 4 1 1 1 1 2 4 8 16 3 9 27 81 4 16 64 256
as can be seen more clearly if we lay it out like this:
(Since the outer product involves operations between all elements, rather than just between corresponding elements, it's not necessary for the arguments to conform in shape or size.)
The inner product allows two functions to be applied to the arguments. The operations take place between the last dimension of the left argument and the first dimension of the right argument, hence 'inner' product since the two inner dimensions are used.
In the case of matrices, first each row of the left argument is applied to each column of the right argument using the rightmost function of the inner product, then the leftmost function is applied to the result, in a reduction (
Given that you can use a combination of any two suitable functions, there are over 400 possible inner products! Obviously these can perform a variety of useful operations. Some of the more common uses are:
As its name implies, the each operator will apply a function to each element of an array.
So, to find the lengths of an array of vectors
⍴¨(1 2 3)(1 2)(1 2 3 4 5) 3 2 5
As with other operators, each can be used for user-defined functions. Here we use an average function on an array of vectors.
AVERAGE 1 2 3 2 AVERAGE ¨ (1 2 3) (4 5 6) (10 100 1000) 2 5 370
When a function operates on data of more than one dimension, there is a choice as to which dimension it should work on.
The default which APL takes if you don't specify otherwise is to operate on the last dimension. The order of dimensions is the order in which they are defined in a
If you want to specify a different dimension, you can do so by putting the number of the required dimension in square brackets after the function or operator.
Here's a data structure of two dimensions, called
TAB ← 2 3 ⍴ ⍳6 TAB 1 2 3 4 5 6 +/TAB 6 15
Since no dimension was specified, the summing operation requested by
This statement specifies that the operation should be done, instead, on the first dimension, the rows;
+/TAB 5 7 9
The elements in row 1 were added to the corresponding elements in row 2.
As you would expect, the following statement (which specifies the second dimension, the columns) is equivalent to the first example where no dimension was specified:
+/ TAB 6 15
Here's an example using the
⌽TAB 3 2 1 6 5 4
Again it has been applied to the last dimension (the columns) by default. What was column 3 is now column 1 and visa-versa.
Here the first dimension is specified:
⌽TAB 4 5 6 1 2 3
Row 1 has changed places with row 2.
Below is a three-dimensional structure such as would be set up by this
DATA ← 2 2 3⍴⍳12 DATA 1 2 3 4 5 6 7 8 9 10 11 12
The first dimension consists of two planes (the two blocks of numbers). The second dimension is the rows, two in each plane. The third is the columns, three in each row.
The following statement specifies a multiplication operation on the second dimension. In other words, row 1 is to be multiplied by row 2 in both planes
×/DATA 4 10 18 70 88 108
The first line is the result of multiplying row 1 by row 2 in the first plane. The second line is the result of the equivalent operation for the second plane.
The first dimension consists of the two planes. A multiplication on the first dimension will multiply each element in plane 1 by the corresponding element in plane 2:
×/DATA 7 16 27 40 55 72
You'll find other examples of the use of
The list of built-in functions and operators that accept an axis specification is:
For more details see the APLX Language Manual
Copyright © 1996-2008 MicroAPL Ltd