You may already have looked this up in the APLX Language Manual as suggested at the end of session 1. But since it's used in one of the functions you're going to write, we'll cover it briefly just in case.
/ is called Slash or Reduce.
Note that in the context in which we're describing it here,
/ is an operator not a function; it modifies or extends the operation of the functions it's used with. Here's an example of its use:
+/ 1 6 3 4
/ did was to extend the operation of
+ so that the expression effectively became:
Here's an example using multiply:
×/ 1 2 3 4
Multiply was used on each number in the list like this:
Let's see how this works on a table:
TABLE ← 3 3 ⍴⍳9
1 2 3
4 5 6
7 8 9
6 15 24
It won't take you a moment to work out what APL has done to produce the three numbers
6 15 24.
Obviously they're the sum of the numbers in each row. (If you want to make the
+/ operation apply to columns instead of rows, this is easily done. It's explained under the entry for
, Axes, in the APLX Language Manual.)
Remembering APL's rule of working from right to left, and the fact that one function's results are data to the next function down the line, enter an expression that will sum all the numbers in the table.
This is one solution:
+/ +/ TABLE
We know that the result of the first (ie the right-hand) part of the statement is
6 15 24. So these three numbers are the data for the left-hand
+/. Their sum is
You can add the numbers in just one column by the usual method of indexing. Here's
TABLE again followed by a statement which adds the numbers in the first column:
1 2 3
4 5 6
7 8 9
+/ TABLE [;1]
Here's a useful combination: the function
⌈ used with
/ selects the largest number from a list:
⌈/75 72 78 90 69 77 81 88
While the equivalent
⌊ statement naturally produces the smallest number:
⌊/ 75 72 78 90 69 77 81 88
In case it crossed your mind that
⌊ were being used in their one-argument forms in the last two examples, remember that what
/ does is to put the function (
⌊ or whatever) between each element of the data it's applied to like this:
75 ⌈ 72 ⌈ 78 ⌈ 90 ⌈ 69 ⌈ 77 ⌈ 81 ⌈ 88
Here's a final example of the use of
/ for you to ponder before you go on to the topic of function definition. What does this example do?
X ← 1 2 3 4 5
Hitherto your APL statements have worked their way up the screen and, when they reached the top, have disappeared without trace. You're about to learn how to preserve statements, or groups of statements, so that you can summon them back for execution or amendment at any time. In other words you're going to find out how to write a function. A user-defined function in APL is like a program in another language. It has a name and consists of APL statements. When you quote the name, the statements are executed consecutively, or in whatever order you specified when you defined the function.
Writing a Function
In most versions of APLX, there are two ways to create or edit a function.
The most commonly used way is to use a full-screen editor, which allows you to edit the function text very easily in an editor window. The editor is either invoked through the application's Edit menu, or with the
)EDIT system command (or the
⎕EDIT system function), e.g.
Here is a snapshot of an editor window on a Windows system, showing a function called
DEMO_Taskbar being edited:
For backward compatibility with old APL systems, APLX also supports a primitive line-at-a-time editor called the Del editor. To enter definition mode and create a new function you type
∇ (Del) followed by the function name. If you type nothing else, you are defining a function that will take no arguments:
You will probably never need to learn the Del editor. If you do accidentally type a
∇ character to enter definition mode, just type another
∇ to get back to calculator mode.
For clarity, we will list functions here as though they were entered using the Del editor, where a
∇ character is used to mark the start and end of the function listing. Listing functions in this way makes it clear at a glance that you are looking at a function. It's also a convention commonly used in other APL documentation on the Internet.
If you are using the normal full-screen editor, you do not type the
∇ characters or the line numbers.
APL requires to know the name of the function you're defining. Your first function will be called
TRY1 so enter:
Enter the following function (Remember that you don't type the
∇ or the line numbers):
 'Type some numbers: '
 NUM ← ⎕
 'Total is: '(+/NUM)
⎕ symbol is called Quad and is found on the 'L' on the keyboard. What the
⎕ does will be quite clear in a couple of minutes)
Here's the complete function shown in an APLX editor window. Don't worry about the colours for now; APLX uses syntax colouring to show different types of symbol.
To save the function, select 'Save (fix) in workspace' from the editor window's File menu and then close the window.
Running a Function
Now you're ready to run the function you've written. Type the function name to run it:
Type some numbers:
Type in a few numbers as the message suggests:
93 7 0 2
Total is: 102
If you get errors while running a function (e.g because you made a typing mistake), APLX will normally ask you whether to show the Debug window:
For now, just answer 'No' and then use
)EDIT TRY1 to get back to the edit window, where you can correct your mistake. Alternatively if you're ready to explore further, answer 'Yes' and then correct the mistake directly in the Debug window.
Now you've seen what the function does, we'll go very briefly through the APL statements that make it up.
- Line 1 was entered as:
'Type some numbers: '
It behaves exactly as you'd expect. When the function is executed, the text in quotes is displayed on the screen.
- Line 2 consisted of:
NUM ← ⎕
⎕), as used here, tells APL to wait for something to be typed in on the keyboard. So this line means 'Accept some input from the keyboard, then assign that input to the variable
NUM'. Line 2 was responsible for the invitation to type (ie the Quad symbol and colon) which appeared after the line of text when the function was executed.
- Line 3 was as follows:
'Total is: '(+/NUM)
Working from the right, it first adds the numbers in
NUM,that is, the numbers which were typed in, then it displays the result preceded by the text "
Total is: ". We have made up a nested list (remember the rules about parentheses).
Editing a function
Now suppose you want to add a line to this function, telling the user how many numbers he or she typed in. To modify the function, just open a new edit window:
You want to insert a step to display a message saying how many numbers were entered. This step should go between the present lines 2 and 3:
'You have entered' (⍴NUM) 'numbers'
Run your amended function and check that it works:
Type some numbers:
93 7 0 2
You have entered 4 numbers
Total is: 102
How about inserting yet another step? You no doubt recognised that the statement you were left to ponder earlier in this chapter worked out the average of a group of numbers.
Why not insert a step at the end of
TRY1 which displays the average of the numbers in
NUM? Rejoin the manual when you've done that.
Line 5 of
TRY1 should now look like this, though your text in quotes may be different:
'Average is:' ((+/NUM)÷⍴NUM)
See if it runs then read on regardless of the result!
Now make use of the function editor to add a couple of lines to
TRY1. You want the function to print out the biggest and smallest of the numbers entered, together with some suitable text.
Hopefully all went well, and you ended up with a function looking something like this:
 'Type some numbers: '
 NUM ← ⎕
 'You have entered' (⍴NUM) 'numbers'
 'The biggest was: ' (⌈/NUM)
 'The smallest was: ' (⌊/NUM)
 'Total is: '(+/NUM)
 'Average is:' ((+/NUM)÷⍴NUM)
Saving a workspace
So far you have saved the function
TRY1 in the workspace, but the workspace itself has not been saved to disk. If you were to end your APL session now all your work would be lost.
You may have doubts about saving the workspace containing
TRY1. But do it anyway as a dry run for when you have something you really want to save.
First check what variables you have in your workspace:
NUM TABLE X (your list may be different.)
There's a system command for enquiring about functions which you can now use:
You're going to save the workspace, so you may as well first erase
X and any other variables you have in your workspace which aren't needed by
)ERASE TABLE X
)ERASE is another system command. It lets you erase one or several variables or functions from the workspace in memory. You can check that the erasures took place by issuing another
)VARS if you want.
The next step is to save your workspace. For GUI versions of APLX, the easiest way to save a workspace to disk is to use the "Save )SAVE" command in the File menu. If the workspace has not yet been saved, this will display a standard file selection dialog box asking you where you want to save it.
On subsequent occasions, the copy of the workspace on disk will be updated each time you select Save again.
Now you know that workspace is saved on disc, you can clear the workspace in memory using the familiar command:
You can check that it's worked by typing:
TRY1 is no longer there.
You can get the workspace back into memory by selecting the "Open... )LOAD" item in the File menu. When you choose this menu item, a second dialog box usually appears to warn you that the operation you are about to perform will overwrite your current active workspace (you can disable this feature using the APLX Preferences dialog). This will only happen if you are not in a clear workspace.
You will then be asked which workspace you want to load, using the standard file selection dialog box.
The workspace you select will be read into memory. Check that
TRY1 is back by issuing a
User functions with arguments
If you compare
TRY1 with the functions built-in to APL, one point should strike you:
TRY1 has no arguments.
User functions can, in fact, have no arguments, one argument or two arguments.
Let's take the expression used in
TRY1 to find the average of the numbers and define it as a one-argument function called
AV. The intention is that once
AV exists, we should be able to use it like a built-in APL function. We should, for example, be able to type:
AV 12 7 3 1
and get a result which is the average of the numbers on the right.
Here's the first line of
AV, known as the function header statement. When defining the function header, we have to indicate that the function will take an argument to its right:
X to represent the right-hand argument, that is, the data
AV will work on.
Here's the complete function:
We've assumed the numbers to be averaged are in the variable called
X. That's all there is to
AV, so create the function using
)EDIT AV and try it out:
AV 3 8 1 4
AV 192 4534 12 0 2
It will work equally well if the right-hand argument is a variable:
NUM ← 1 2 3 4 5
As you can see, any value to the right of
AV, whether a directly-quoted number, or a value in a variable, is substituted for the
X we used in the function definition.
User functions with two arguments work very similarly. In the function header, the arguments are represented by variable names on either side of the function name. For example, for a function called
MPH intended to work on two arguments, namely distance and time, the header might be:
∇D MPH T
AV printed its result directly to the screen. If you want the function to return a result which can be used in further APL expressions, you need to change
AV as follows:
Here, the average is assigned to a result
R, allowing you to do things like:
¯3 + AV 3 8 1 4
But you'll have to find out about this, and other types of user-defined functions, on your own. We will return to the subject in a later chapter.
Functions within functions
There's no reason why
AV should not be used in
TRY1 to work out the average of the numbers input and held in
TRY1, then check that the new arrangement works.