Topic: APLX Help : Help on APL language : APL Fundamentals : Defined Functions
[ Previous | Next | Contents | Index | APL Home ]

User-defined Functions

User-defined functions are the equivalent of subroutines or functions in other programming languages. They associate a series of lines of APL code with a name chosen by the programmer.

When a function is evaluated, it performs some action on data known as an 'argument'. Functions may have no arguments, one argument, or two arguments. These three types of functions are often referred to as follows:

               0 arguments             Niladic
               1 argument              Monadic       Argument on right
               2 arguments             Dyadic        Arguments on left and right

If you defined a function called. say, SD which found the standard deviation of a set of numbers, you could write it so that it expected the data as its right-hand argument. You would then call SD in exactly the same way as a primitive function such as :

      X ← SD 23 89 56 12 99 2 16 92

A function may or may not return a result.

You specify the number of arguments the function is to have, and the name of the result field (if there is one) when you define the function header of the function you are about to write.

Header line for user-defined functions

In addition to the names used for the left and right arguments and result (if applicable) which will all be 'local', the header line may also be used to localize other variables (and system variables), as well as function names. Whilst the function or operator is running, these local variables 'shadow' global variables of the same name, that is they will exclude from use a global object of the same name. System commands continue to reference the global objects. Local variables (and functions) are however themselves global to functions called within their function or operator.

The general format for a function header is:

             R← A FUNCTION B;VAR1;VAR2
                A FUNCTION B;VAR1;VAR2

depending on whether or not a result is returned. R, the result, A, the left argument, B, the right argument are all optional. Local names, if any, are listed after the function name and arguments, separated from them and each other by semi-colons (;), VAR1 and VAR2 above. Comments may also appear at the end of the header line, following a ('comment') symbol.

Editing functions

In most versions of APLX, there are two ways to create or edit a function.

The most commonly used way is to use an on-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.

      )EDIT FUNK

For backward compatibility with old APL systems, APLX also supports a primitive line-at-a-time editor called the Del (or Line) 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:


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. If you are using the on-screen editor, you do not type the characters or the line numbers.

The function header

The first line of a function is called the function header. This example is the header for a function called FUNK:


If you want the function you are defining to have arguments you must put them in the header by typing a suitable function header:

      ∇SD X

The above header specifies that SD will take one argument. Here is what SD might look like when you had defined it:

      ∇SD X
  [1] SUM ← +/X
  [2] AV ← SUM÷⍴X
  [3] DIFF ← AV-X
  [4] SQDIFF ← DIFF*2
  [6] RESULT ← SQAV*0.5

It's quite unimportant what the statements in the function are doing. The point to notice is that they use the variable X named in the function header. When SD is run, the numbers typed as its right-hand argument will be put into X and will be the data to the statements that use X in the function. So if you type:

      SD 12 45 20 68 92 108

those numbers are put in X. Even if you type the name of a variable instead of the numbers themselves, the numbers in the variable will be put into X.

The function header for a dyadic (two-argument) function would be defined on the same lines:

      ∇X CALC Y

When you subsequently use CALC you can supply two arguments:

      1 4 7 CALC 0 92 3

When CALC is run the left argument will be put into X and the right argument into Y.

If you want the result of a function to be put into a specified variable, you can arrange that in the function header too:

      ∇Z ← X CALC Y

In practice, most APL functions return a result, which can then be used in expressions for further calculations, or stored in variables.

Defining Z to be the result of X CALC Y allows the outcome of CALC to be either assigned to a variable, or passed as a right argument to another (possibly user-defined) function, or simply displayed, by not making any assignment. The variable Z acts as a kind of surrogate for the final result during execution of CALC.

Local and global variables

Variable names quoted in the header of a function are local. They exist only while the function is running and it doesn't matter if they duplicate the names of other variables in the workspace.

The other variables - those used in the body of a function but not quoted in the header, or those created in calculator mode - are called global variables.

In the SD example above, X was named in the header so X is a local variable. If another X already exists in the workspace, there will be no problem. When SD is called, the X local to SD will be set up and will be the one used. The other X will take second place till the function has been executed - and of course, its value won't be affected by anything done to the local X. The process whereby a local name overrides a global name is known as 'shadowing'.

It is obviously convenient to use local variables in a function. It means that if you decide to make use of a function written some time before, you do not have to worry about the variable names it uses duplicating names already in the workspace.

But to go back to the SD example. Only X is quoted in the header, so only X is local. It uses a number of other variables, including one called SUM. If you already had a variable called SUM in the workspace, running SD would change its value.

You can 'localize' any variable used in a function by putting a semicolon at the end of the function header and typing the variable name after it:

      ∇SD X;SUM

You may wonder what happens if functions that call each other use duplicate local variable names. You can think of the functions as forming a stack with the one currently running at the top, the one that called it next down, and so on. A reference to a local variable name applies to the variable used by the function currently at the top of the stack.

Comments in functions

If you want to include comments in a function, simply enter them, preceded by a comment symbol.

      ∇R ← AV X
  [1] ⍝ This function finds the average of some numbers
  [2] R ← (+/X)÷⍴X ⍝ The numbers are in X

There are two comments in the example above. Note that the one on line 2 doesn't start at the beginning of a line.

Locked functions

It is possible to lock a function. A locked function can only be run. You can not edit it or list the statements it consists of. To lock a function, edit it in the Del editor but type a rather than a to enter or leave function definition mode.

A locked function cannot be unlocked.

Localized functions

Local functions cannot be edited by the standard editor, and the editor will always refer to a global function of the same name (if it exists). ⎕CR may be used to examine local functions.

Ambivalent functions

All dyadic functions may be used monadically. If used monadically, the left argument is undefined (i.e. has a Name Classification, ⎕NC of 0). This type of function is known as an ambivalent or nomadic function, and will usually start by testing for the existence of the left argument.

             ∇R←A NOMADIC B
       [1] :If 0=⎕NC 'A'        ⍝ DOES A EXIST?
       [2]   A←5                ⍝ NO, SO WE HAVE BEEN USED MONADICALLY
       [3] :EndIf

Topic: APLX Help : Help on APL language : APL Fundamentals : Defined Functions
[ Previous | Next | Contents | Index | APL Home ]