GNU APL is shipped with different kinds of documentation for different
purposes to be used at different times:
A number of README files in the top-level directory. These files
shall help with specific issues in the configuration of the interpreter,
i.e. before the interpreter is compiled and/or after it is installed.
man apl (in a terminal window) displays a list of all command line
options understood by GNU APL.
The )HELP command of the interpreter:
)HELP without an argument prints a list of APL commands,
APL system functions, and APL system variables known by
the interpreter,
)HELP primitive shows a more detailed help for the given
primitive (if such help is available).
This document (Quick Tour). It is a little more detailed, with a focus
on examples. This is supposedly the best starting point for readers
that are new to APL in general or to GNU APL in particular.
info apl (in a terminal window). More detailed with a focus on only
GNU APL specific features that are not available in, or differ from,
standard APL.
A number of files in the HOWTOs directory. These files describe
some of the non-trivial GNU APL system functions.
All documentation is available on the local machine after GNU APL
was successfully installed, and some of it is also available online
via the GNU APL home page https://www.gnu.org/software/apl.
1.2 Conventions in This Document
Keyboard input is rendered in blue
and the response from the GNU APL interpreter is black like this:
This is what you type on the keyboard
and this is the response you get for correct input
1+ ⍝ In contrast, APL ERROR messages are shown in red:
SYNTAX ERROR
1+
^^
Error messages from the interpreter are shown in
red. This coloring of input, output,
and error lines above is the default, but it is possible to change the
colors, or (e.g. if GNU APL is run as a script) to disable the
colorization completely.
2 Starting and stopping the APL interpreter
APL is an easy-to-learn language. This quick start manual is an introduction
to APL in a few simple steps. We assume that you are using GNU APL and that
you have installed it according to the README files that came with it.
The APL interpreter is a normal program and is started like that: by entering
its name in a shell (preferably bash).
$ apl
______ _ __ __ __ ___ ____ __
/ ____// | / // / / / / | / __ \ / /
/ / __ / |/ // / / / / /| | / /_/ // /
/ /_/ // /| // /_/ / / ___ | / ____// /___
\____//_/ |_/ \____/ /_/ |_|/_/ /_____/
Welcome to GNU APL version 1.8
Copyright (C) 2008-2022 Dr. Jürgen Sauermann
Banner by FIGlet: www.figlet.org
This program comes with ABSOLUTELY NO WARRANTY;
for details run: ./apl --gpl.
This program is free software, and you are welcome to redistribute it
according to the GNU Public License (GPL) version 3 or later.
The interpreter prints a start-up banner like that shown above and then enters
an endless loop which APL programmers refer to as immediate execution mode
and others as REPL (an abbreviation for
Read-Evaluate-Print-Loop).
In immediate execution mode the interpreter reads one input line, either
interactively from the user, or from a file if GNU APL is run as a script.
It then processes (or Evaluates in REPL) the input line and
prints some result output (which may be empty for some input lines).
Depending on the details of the processing of the line entered, the
interpreter will either:
remain in immediate execution mode (the Loop in REPL), or
enter another mode called definition mode, or
exit the interpreter
The following state machine describes this top-level behavior of an APL
interpreter, and some user inputs that trigger mode changes:
In the first case, i.e. the interpreter remains in immediate execution mode,
the whole process starts over again; the next line is read, processed, printed,
and so on.
The second case (leaving immediate execution mode) is explained in a later
chapter.
The first non-blank character of the line entered in immediate execution mode
determines what happens next:
if the first non-blank character is either ) or ] then the
line is interpreted and processed as an APL command. Commands are
discussed in chapter "Commands" below. Commands that start with ]
instead of ) are a GNU APL extension of standard APL.
if the first non-blank character is ∇ then an APL function editor
(the ∇-editor) is started and editing of a new or already existing
user-defined function begins until ∇ is typed again. User-defined
functions are simply called defined functions in APL jargon.
The construction and editing of defined functions is discussed in chapter
Defined Functions below.
Otherwise the line is considered a sequence of APL statements and the
interpreter enters execution mode (which corresponds to the
Evaluate in REPL) in which APL code is being executed.
The execution mode may have its own loops which may be interrupted
with ^C. The execution mode is left automatically after the last APL
statement was processed, or after an APL error had occurred. APL
statements are discussed in chapter "APL Statements" below.
The most important command at the moment is )OFF which ends the
apl interpreter:
)OFF
Goodbye.
$
Pressing control-C or control-D (i.e. the standard way to end programs)
merely stops the execution of the current APL statement in execution mode,
but does not end the interpreter. This behavior is similar to a shell where
control-C stops the current program but does not exit from the shell.
3 APL Statements
APL statements are constructed from:
APL constants (numbers and characters)
Names (of functions and/or variables)
other characters (APL glyphs) e.g.: ← → [ ; ] + ◊ ÷ ( ) or :
Several statements on the same line are separated by the APL character ◊
(called Diamond). Note that different statements on the same line are
executed from left to right while each statement is evaluated from right
to left. Before discussing the execution of statements we will introduce
their components, i.e. constants and names.
3.1 Constants (Literals)
Constants, also called literals, are used in APL statements for denoting
fixed values.
3.1.1 Scalar Constants
The simplest constants are scalar constants, similar to atoms in Chemistry.
From these scalar constants more complex constants can be created. There are
also scalar APL values which are not constants; a definition of the term
scalar will be given later. For the moment think of a scalar as a single
data item.
3.1.1.1 Scalar Text Constants
The simplest scalar constants are scalar text constants. A scalar text
constant defines a single character.
As we will discuss in more detail later, if you enter a constant
(and nothing else) in immediate execution mode then the interpreter will
transmit it to its output, although in a slightly different fashion.
A scalar text constant (aka. a single character) is entered by enclosing the
character in single quotes. The character A, for example, is entered as 'A'
and the interpreter answers by printing A but removing the quotes around it:
'A'
A
The quote character itself is entered by doubling it inside the quotes
that enclose it:
''''
'
3.1.1.2 Numeric Scalar Constants
A numeric scalar constant is a single number. The simplest numeric scalar
constant is an integer, entered as a sequence of decimal digits:
42
42
Fractional numbers are entered with a decimal point and a fractional part:
42.5
42.5
The integral part can be omitted:
.5
0.5
An optional scaling by a power of 10 (aka. scientific notation) can be applied
with the character E, followed by the exponent. The E is case insensitive,
therefore e will also work:
42.5E3
42500
42e3
42000
Negative numbers use a leading ¯ (Overbar); a minus sign is NOT the sign of
a number but a function that negates a value. The result is often the same,
but you should always use the overbar for negative numbers:
¯42.5E3
¯42500
The exponent in scientific notation can also be negative (in this case using
- gives a different result):
42.5E¯3
0.0425
42.5E-3
VALUE ERROR
42.5 E-3
^
The error in the second statement above occurs because:
in APL the minus sign (i.e. - as opposed to ¯) is a primitive function and
never part of a number, and therefore
the E is not an exponent belonging to 42.5. Instead E is taken
as the name of a variable (which does not exist in this example) and that
causes the error. Using - instead of ¯ is a frequent mistake made by APL
beginners.
Complex numbers can be entered in three different formats. The native format
(native because it is the format used by the interpreter when printing
complex numbers) is to specify the real and imaginary parts of a complex
number separated by the letter J (or j):
3J4 ⍝ a complex number of magnitude 5
3J4
0.6j0.8 ⍝ the same, but scaled to magnitude 1
0.6J0.8
One alternative format is to specify the number as its magnitude and its
angle in degrees (from 0° to 360°), separated by the letter D or d (which
stands for "degrees"). Since arccos(0.6) = 53.130102354, we get the
same complex numbers:
5D53.130102354 ⍝ magnitude 5, angle 53.130102354°
3J4
1d53.130102354 ⍝ the same, but scaled to magnitude 1
0.6J0.8
The other alternative format is to specify the number as its magnitude and its
angle in radians (from 0 to 2π), separated by the letter R or r (for
"radians"). Since 53.130102354 π ÷ 180 = 0.927295218 we get the same numbers:
1r0.927295218 ⍝ the same, but scaled to magnitude 1
0.6J0.8
Please keep in mind that whitespace characters (space, tab, etc.) are NOT
permitted in numbers.
3.1.2 Vector Constants
Vector constants are created by writing several scalar constants on the
same line, separated by one or more spaces between them. A single complex
number is a scalar even if has two components (its real and imaginary parts).
Multiple separating spaces between scalars are treated like single spaces:
1 2 3
1 2 3
'A' 'B' 'C'
ABC
Sequences of character scalars can be written with quotes around the sequence
rather than quotes around each character. The rules for scalar character
constants apply here as well:
'ABC'
ABC
'A''B''C'
A'B'C
"A'B'C"
A'B'C
You cannot enter numeric vector constants with less than two elements because
numeric vector constants with one element would be a numeric scalar constant,
and numeric vector constants with no elements would be completely empty.
You can enter an empty character vector constant (a vector with no elements)
like this:
''
""
You normally cannot enter character vector constants with one element for
the same reason as for numeric vector constants: it would be a scalar
constant rather than a vector. This can become cumbersome when dealing with
text; if the length of a character sequence is one then the text is a scalar,
otherwise it is a vector. For this reason GNU APL provides a non-standard
extension using double quotes instead of single quotes. This extension has
slightly different and sometimes more convenient rules than texts in single
quotes:
double quoted characters are always vectors (even if their length is 1)
single quotes stand for themselves and need not be doubled
for some problematic characters C-like sequences are defined:
Finally, in the old APL1 (ISO 8485 standard) there was no way to express
an empty numeric vector and one had to use expressions like ⍳0 or
0⍴0 for them. In modern interpreters, however, the symbol ⍬ may
be used to denote an empty numeric vector (i.e. of length 0). In APL1 empty
numeric vectors were often expressed as '', frequently as ''⍴V to get the
first item of a vector or matrix into a scalar. That worked, but these days
one would use the cleaner ⍬⍴V instead.
3.1.3 Mixed Constants
The first APL interpreters (and the first APL standard, ISO 8485) only allowed
constants and values whose components were either all numeric scalars, or all
character scalars. The examples given so far were of that kind.
The current APL standard, ISO 13751, also allows a mix of characters and
numbers in constants and values, for example:
1 2 'A' 'B' 3 4
1 2 AB 3 4
Such values are called mixed.
3.1.4 Nested Constants
The vector constants discussed so far were simple, which means that their
components were (numeric or character) scalars. Since ISO 13751, another
APL value can be used instead of a scalar. Such constants or values are called
nested. The nested components of constants are vectors that are
either quoted texts (aka. strings) or, if numeric, surrounded by
parentheses instead of quotes:
1 2 'AB' 3 4 ⍝ (nested) string 'AB'
1 2 AB 3 4
1 2 (10 11) 3 4 ⍝ nested numeric vector (10 11)
1 2 10 11 3 4
In the normal output formatting of APL like above, the nesting of items is
displayed as additional blanks which makes it sometimes difficult to recognize
the exact nesting structure. The quotes and parentheses that group the items
of a nested literal on input are replaced by blanks on output. That blurs
the output, in particular when the nesting becomes deeper (i.e. when a nested
value contains nested items). Nested values differ from non-nested values
comprised of the same scalars only by the number spaces between the scalars,
which is difficult to see if the values are long or deeply nested.
For that reason, APL interpreters often come with functions, either built-in
or defined functions that display the structure of nested values in a clearer
way. In IBM APL2 these functions are called DISPLAY and DISPLAYC (in workspace
DISPLAY, the two functions slightly differ in style). In GNU APL the functions
are built-in and are several subfunctions of dyadic ⎕CR (e.g. 4 ⎕CR and 8 ⎕CR,
also slightly differing in style). In GNU APL, ⎕CR is a collection of more
than 40 subfunctions, some of which play the roles of DISPLAY in IBM APL2.
For example:
Some users prefer that APL output is always displayed in the format of 8 ⎕CR
(or in one of the other styles that ⎕CR provides). This can be achived by a
GNU APL command:
1 2 'AB' 3 4 ⍝ by default: standard output formatting
That approach becomes rather cumbersome and inefficient when the number
of text rows is large (a single long line would "blow up" the other lines
to its length, yielding a larger than necessary matrix that consist mostly
of trailing spaces). In the days of APL1 that was sort of acceptable
because the focus was more on numerical computations rather than text
processing and the rare texts were mostly used as short decorators
for the numbers displayed.
Things have changed since then and with the advent of nested values in APL2
one would express long texts as a vector of nested strings rather than as
character matrices:
"Peter" "Paul" "Mary" ⍝ nested 3-item APL2 vector (note the lack of trailing input spaces and the output indentation)
Peter Paul Mary
⊃ "Peter" "Paul" "Mary" ⍝ back to APL1 text matrix (not indented)
Peter
Paul
Mary
Even though this improves over APL1, it is still cumbersome if the number
of lines is large or not known beforehand. In that case one often finds,
even in APL2, constructs like:
TEXT←3⍴0 ⍝ reserve space for 3 (nested) lines
TEXT[1]←⊂'Peter' ⍝ ⊂ turns text vector 'Peter' into a nested scalar
TEXT[2]←⊂'Paul'
TEXT[3]←⊂'Mary'
⊃ TEXT
Peter
Paul
Mary
Or, even worse (since the execution time increases quadratically with the
number of lines):
TEXT←⍬ ⍝ start with an empty vector
TEXT ← TEXT, ⊂'Peter' ⍝ append line 'Peter'
TEXT ← TEXT, ⊂'Paul' ⍝ append line 'Paul' (no trailing space needed)
TEXT ← TEXT, ⊂'Mary' ⍝ append line 'Mary' (no trailing space needed)
⊃ TEXT
Peter
Paul
Mary
To further improve and simplify the specification of multi-line texts, which
is a problem that often occurs in real life APL programs, GNU APL has adopted
the concept of multi-line strings from the Python language or from
the bash shell. A multi-line string starts and ends with triple quotes
and the lines between become a nested text vector:
Note the → prompt (from APL), which indicates that a multi-line string has
started but not yet ended. The characters in the triple quotes shall be either
" or else (double angle quotes) « in the leading and » in the
trailing triple quotes (the same holds, BTW also for normal GNU APL strings.
Intelligent editors are able to jump back and forth between matching quotes,
but only if the leading quote differs from the trailing quote. Use this
capability with care, since it undermines the portability of APL code written
for GNU APL.
3.1.6 Summary and Remarks
Constants are used for creating fixed APL values. There are many APL values
that cannot be expressed by constants, for example numeric vectors with only
one component, or higher-dimensional values like matrices. These values
can only be created using functions (as explained further down).
3.2 APL Names
APL knows 3 kinds of names:
user defined names,
names of system functions and variables, and
names of primitive APL functions (or primitives for short)
3.2.1 User-defined Names
User-defined names start with a letter (A-Z or a-z) or one of the 3 characters
_ (underscore), ∆ (delta), or ⍙ (delta-underline. The starting
character may be followed by letters, digits, or one of the characters
¯ (overbar), _, ∆, or ⍙. The ∆ and ⍙ characters are often used to separate
some common prefix (for example the name of a library) from the functions
and variables that are somehow related (for example the functions and
variables that belong to a library). User-defined Names are case-sensitive,
i.e. Foo and FOO are different names.
User-defined names are used to denote APL variables, defined functions,
defined operators, or labels in defined functions or operators.
3.2.2 Names of System Functions and System Variables
The names of system functions start with the APL character ⎕ (quad) followed by
a small number of letters. System names are case-insensitive, i.e. ⎕IO is
the same as ⎕io. Older APL programmers seem to prefer uppercase,
presumably because the first APL interpreters had no lowercase characters.
Only a handful of system functions and variables are standardized in the ISO
standards 8485 and 13751, but every APL interpreter adds many more. Those that
are not defined in the standards differ considerably between APL interpreters
from different vendors even if their names are the same. Adding non-standard
system functions and variables are the normal way of adding features to the
APL language; they usually add functions whose implementation in APL would
be inefficient or cumbersome.
3.2.3 Names of Primitive APL Functions
The names of primitive functions are single APL characters that differ from
all characters allowed in user-defined names.
Almost all the primitive APL functions (and hence their names) are
identical in all APL interpreters and are standardized in ISO standard 13751.
Apart from the differences mentioned above, there is no real difference
between system functions and primitive APL functions.
3.3 Functions and Operators
Functions in APL can have none, one, or two arguments.
Those with no argument are called niladic, functions with one argument
are called monadic, and two-argument functions are called dyadic.
Some monadic or dyadic functions can have another, optional, argument used for
specifying an axis (a dimension along which the function is computed). In
standard APL, only primitive APL functions can have an axis argument, but
GNU APL also supports an axis argument for defined functions.
Most dyadic functions can also be called with only one argument. These functions
are called nomadic. This basically means that the same function name is
used for two different functions. The two functions are often related. For
example, ÷ is nomadic; its dyadic variant A ÷ B (called divide) divides A by B
while its monadic variant (called inverse) divides 1 by B. Another way of
putting this is: a nomadic function is a dyadic function whose left argument
is optional (and omitting it changes its behavior).
3.3.1 Niladic Functions
A niladic function takes no arguments. A niladic function call is simply the
name of the niladic function. For example, ⎕TS is a niladic system function
that returns the current time as year, month, day, hours, minutes, seconds,
and milliseconds:
⎕TS
2024 12 13 13 57 51 238
3.3.2 Monadic Functions
A monadic function takes one argument. A monadic function call consists
of the name of the function followed by its sole argument. For example, the
monadic variant of the nomadic function ÷ computes the inverse of its argument:
÷ 2
0.5
÷ 2J2
0.25J¯0.25
If the optional axis argument mentioned above is supported, then it is
placed in brackets immediately to the right of the function name.
3.3.3 Dyadic Functions
A dyadic function takes two arguments. A dyadic function call consists
of the second (aka. left) argument, followed by the name of the function,
followed by its other (aka. right) argument. For example, the
dyadic variant of the nomadic function ÷ computes the left argument divided
by the right argument:
4 ÷ 2
2
4J4 ÷ 2J2
2
As the last example above shows, APL automatically converts numbers to their
simplest form, i.e. from complex to real, from floating point to integer,
and from integer to Boolean. At least it looks like that. A value that
is, for example, printed like an integer may internally still be a real
or even a complex number.
In older APL interpreters there used to be a function ⎕DR (data representation)
that would tell if an APL value was complex, real, integer, or Boolean.
For mixed arrays introduced by ISO 13751 that does not make much sense
anymore so the ⎕DR function has disappeared.
3.3.4 Monadic Operators
APL operators are functions that have one or two value arguments like monadic
or dyadic functions, but in addition take one or two function arguments.
The attribute monadic or dyadic of an operator refers to the
number of function arguments for the operator and not to the number of value
arguments. If OP1 is a monadic operator then (f OP1) is a so-called
derived function; depending on the operator its derived function can
be monadic or dyadic.
A monadic operator is therefore an operator that has one function argument,
and a dyadic operator is an operator that has two function arguments.
As far as built-in APL operators are concerned, one of them (the inner/outer
matrix product . ) is dyadic and all others are monadic.
A monadic operator, together with its function, defines a new function: the
derived function. Likewise, a dyadic operator, together with both
its functions, defines a derived function of that operator. Derived functions
of the same operator but with different function arguments are, of course,
different but they are either all monadic functions or all dyadic functions.
We take presumably the most frequently used operator, reduction, as an
example. The APL symbol for the reduction operator is / (slash). The function
argument of a monadic operator is the function immediately left of the operator
symbol. The reduction operator is monadic (taking one function argument),
the function provided as its function argument must be dyadic, and the derived
function is monadic. The derived function of reduction with function argument
f is also called f-reduction.
When the value argument of f-reduction is a vector, then f-reduction computes
the result of placing f between the vector elements:
f-reduction v1 v2 ... vn ↔ v1 f v2 f ... vn
If function f is + (addition) then f-reduction of a vector is the sum of
its elements:
+/1 2 3 4 5 6
21
Likewise, if f is ⌈ (maximum) then f-reduction of a vector is the largest of
its elements:
⌈/2 5 12 4 0
12
The f-reduction of a matrix is a vector with the f-reduction of each row:
3 3⍴1 2 3 4 5 6 7 8 9
1 2 3
4 5 6
7 8 9
+/ (3 3⍴1 2 3 4 5 6 7 8 9)
6 15 24
f-reduction is one of the functions that support an axis argument.
The axis argument of f-reduction tells along which axis (i.e. rows or columns
in the case of a matrix) the f-reduction shall be performed:
+/[2] (3 3⍴1 2 3 4 5 6 7 8 9)
6 15 24
+/[1] (3 3⍴1 2 3 4 5 6 7 8 9)
12 15 18
In GNU APL, user defined monadic operators can have an axis argument, which
is, like for their built-in pendants, placed in brackets right of the operator
symbol.
3.3.5 Dyadic Operators
A dyadic operator is like a monadic operator but has two function arguments
instead of one.
If OP1 is a dyadic operator then (f OP1 g) is its
derived function. Depending on the operator, its derived functions
can be monadic or dyadic. For some dyadic operators their "function
arguments" may or must be APL values and not functions.
The APL symbol for the inner product operator is . (dot). The function arguments
of the inner product are placed immediately left and immediately right of the
dot. If A and B are matrices, then A +.× B is the normal matrix product:
A←3 3⍴1 2 3 4 5 6 7 8 9
A
1 2 3
4 5 6
7 8 9
A +.× A
30 36 42
66 81 96
102 126 150
In general, for two matrices A and B and functions f and g, the inner product
f.g is a matrix. The element in row i and column j in that matrix is obtained
by applying function g to row i of A and column j of B and then to perform
f-reduction of the (row i column) vector.
Another way of looking at f.g (or at dyadic operators in general) is to
consider (.g) as a derived monadic operator and f.g as f/(.g).
However, dyadic operators cannot have an axis argument.
3.4 General APL Values
The constants introduced so far were examples of APL values. However, many
APL values cannot be written as constants. In this chapter we will introduce
APL values in a more formal way and we will show how arbitrary APL values
can be constructed.
An APL value is defined by two things: a list of scalars that is called
the ravel of the value, and another list that is called the shape
of the value. The shape determines how the ravel is arranged to
produce an APL value.
For example, the same ravel 1 2 3 4 5 6 can be arranged (or "shaped")
in 5 different ways:
1. as a 6-element vector:
1 2 3 4 5 6
2. as a 1 by 6 matrix:
1 2 3 4 5 6
3. as a 2 by 3 matrix:
1 2 3
4 5 6
4. as a 3 by 2 matrix:
1 2
3 4
5 6
5. as a 6 by 1 matrix:
1
2
3
4
5
6
In this example, the shape selects between the 5 possible arrangements
of the ravel. The ravel and the shape are not entirely independent.
Instead the following relation is satisfied by every APL value:
The product of all shape elements is equal to the number of ravel elements
The number of shape elements, also called the rank of the value,
determines how many elements the shape has:
Rank
Commonly called
0
Scalar (no shape dimension)
1
Vector (one shape dimension)
2
Matrix (two shape dimensions)
3
Cube (three shape dimensions)
...
values with higher ranks (more than 3 shape dimensions)
A value also has a depth which tells the level of nesting. Simple scalars
have a depth if 0. All other values have a depth of
(1 + the maximum depth of all ravel elements). Unlike the shape, which can be
imposed on a value, the depth is a consequence of the rank (scalar or not) and
the ravel of the value.
APL programming is the art of creating new APL values from other APL values.
The starting point is the constants discussed above and the new APL values
are created from existing APL values by calling functions with the existing
APL values as function arguments.
You have probably heard that APL has a large number of built-in functions.
As a consequence, the same new APL value can usually be created in many
different ways. APL programmers tend to prefer the way that contains the
smallest number of function calls, even though that is not always the
"cleanest" way.
It is not always obvious how to create a particular APL value. Therefore we
present a (somewhat awkward) method that always works. This method uses only
a handful of built-in APL functions that - no surprise - belong to the most
frequently used functions in APL programs.
3.4.1 Reshape and Shape: ⍴
Reshape is a simple, but powerful, function that creates values of arbitrary
shapes. The function call A ⍴ B returns a new APL value Z with shape A and
a ravel constructed from the ravel of value B as follows.
Let len_B be the number of elements in the ravel of B, and
let len_Z be the number of elements in the ravel of Z.
If len_Z = len_B, then the ravel of Z are the ravel of B.
If len_Z < len_B, then the ravel of Z are the first len_Z elements
of the ravel of B.
If len_Z > len_B, then the ravel of B is appended to itself until one
of the cases above occurs.
Note that the shape of B plays no role in the computation of function reshape.
Most frequently scalars and vectors are being reshaped.
We can now enter the 5 examples above (which are all cases where
len_Z = len_B) in APL:
6 ⍴ 1 2 3 4 5 6
1 2 3 4 5 6
1 6 ⍴ 1 2 3 4 5 6
1 2 3 4 5 6
2 3 ⍴ 1 2 3 4 5 6
1 2 3
4 5 6
3 2 ⍴ 1 2 3 4 5 6
1 2
3 4
5 6
6 1 ⍴ 1 2 3 4 5 6
1
2
3
4
5
6
An example with len_Z < len_B) is this:
2 2 ⍴ 1 2 3 4 5 6
1 2
3 4
The most powerful case is len_Z > len_B, in particular when len_B is small:
Another illustrative example is the creation of a unity matrix. We will later
repeat the creation of a unity matrix with other functions. Creating a
unity matrix with function reshape is somewhat less "clean" than other
methods, but short and effective (and therefore frequently seen in APL code):
5 5 ⍴ 1 0 0 0 0 0
1 0 0 0 0
0 1 0 0 0
0 0 1 0 0
0 0 0 1 0
0 0 0 0 1
The monadic variant of ⍴ is called Shape and returns the shape of its
right argument:
⍴ 1 0 0 0 0 0
6
⍴ (5 5⍴1 0 0 0 0 0)
5 5
The parentheses in the last example are not required, but were added for
clarity. Like in other languages, expressions in parentheses are evaluated
first and the result replaces the parentheses and their content.
The shape of a scalar is an empty vector. Empty vectors produce
an empty APL output:
⍴ 5 ⍝ Shape of a numeric scalar (output is an empty vector)
⍴ ' ' ⍝ Shape of a character scalar (output is an empty vector)
⍴ '' ⍝ Shape of an empty vector
0
3.4.2 Catenate and Ravel: , and ⍪
The next important function on the way to arbitrary APL values is "catenate",
or dyadic , (comma). The function call A , B appends values A and B. If A
and B are scalars or vectors then the result is somewhat obvious:
If A or B is a matrix or a value with even higher rank, then there are
different ways to catenate two values. This is where the optional axis comes
into play. The axis argument determines along which axis
the concatenation shall take place:
2 2⍴'A'
AA
AA
2 2⍴'B'
BB
BB
(2 2⍴'A') ,[1] (2 2⍴'B')
AA
AA
BB
BB
(2 2⍴'A'),[2] (2 2⍴'B')
AABB
AABB
The axes of a value are the different elements of its shape vector. A scalar
has no axes, a vector has one axis, a matrix has two axes, and so on. When
an APL value is printed then the last axis of the value is printed
horizontally (on the same output line) while the other axes are printed
vertically (on different output lines). The default axis for catenate
(i.e. the axis used when no axis argument is given) is the last axis.
There is a companion function of , (comma) namely ⍪ (comma-bar) that is
identical to comma if an axis is provided, but uses the first axis rather
than the last axis if not. Therefore the last two examples could have
been written without an axis argument like this:
(2 2⍴'A') ⍪ (2 2⍴'B')
AA
AA
BB
BB
(2 2⍴'A') , (2 2⍴'B')
AABB
AABB
Note: There are some more function pairs that differ only by their default
behavior when no axis argument is given: ⊖ and ⌽, / and ⌿, and \ and ⍀.
The variant with - in the symbol takes the first axis by default while the
other variant takes the last axis.
The monadic variant of , and ⍪ is a monadic function called "ravel" and
returns the ravel of the value. While function reshape can be used,
among other things, to create values of higher or lower ranks than vectors,
function ravel does the opposite: it brings the rank of values with higher
or lower ranks down to rank 1. In other words, function ravel converts a
value with arbitrary shape to a vector. If a value is a vector already then
function ravel returns (a copy of) that vector.
3.4.3 Universal Character Set (monadic ⎕UCS)
Function ⎕UCS is monadic and computes a value with the same shape as its
right argument. The right argument must be simple (i.e. not nested) values
whose ravel consists of all integers or all characters. Integers are
converted to characters with the same Unicode, while characters are converted
to an integer with the Unicode of the character.
In most cases the characters that you use in strings will be on your
keyboard, but function ⎕UCS can be used if they are not.
Examples:
⎕UCS 65 80 76 32 9076 9066 32 36 165 163 8364 9063 32 196 214 220 228 246 252 223 ⍝ And back to Unicode
APL ⍴⍪ $¥£€⍧ ÄÖÜäöüß
3.4.4 Construction of arbitrary simple values
The functions reshape, catenate, and occasionally ⎕UCS can be combined
to construct arbitrary simple (i.e. not nested) values. We assume,
of course, that it is known how the value shall look. The algorithm
for constructing the new value is then:
construct the shape vector of the new value from smaller items such
as integer scalars or vectors. The integer scalars can be constants or
other integer vectors computed elsewhere. Concatenate (dyadic ,) the
smaller pieces as needed. Put everything in parentheses (in many cases the
parentheses are optional and can be removed, but to be on the safe side we
leave them in).
construct the ravel of the new value from smaller items such as
integer scalars, integer vectors, character scalars and character vectors.
Possibly use ⎕UCS to create single charactera or character vectors using
their Unicode. Concatenate (dyadic ,) the smaller pieces as needed.
reshape the ravel with the shape vector using dyadic ⍴.
Steps 1 and 2 are independent, so you can do 2 before 1.
As an alert reader you will have noticed that you cannot create new
scalars because a scalar has a shape vector of length 0, and we
have seen earlier that empty integer constants do not exist.
In older APL interpreters this was solved by using an empty character
vector instead of an empty integer vector:
'' ⍴ 1 2 3 4 5 6 ⍝ reshape 1 2 3 4 5 6 to a scalar
1
⍴ ('' ⍴ 1 2 3 4 5 6) ⍝ shape of '' ⍴ 1 2 3 4 5 6
This worked well and you will find ''⍴ all over the place in older APL programs.
In newer APL interpreters, including GNU APL, a constant ⍬ (zilde) was
introduced. ⍬ is an empty numeric vector. ⍬⍴ is cleaner than ''⍴ because
a shape should always be an integer vector, but the portability of APL programs
using ''⍴ is better than that of ⍬⍴.
You may also wonder if vectors can be created with the above algorithm (and
remembering that there are not only no integer vector constants of length 0,
but also no integer vector constants of length 1).
The answer is "yes" because the left argument A of A⍴B can be a vector
or a scalar (the scalar is then treated like a 1-element vector).
Note also, that when creating arbitrary simple vectors, Step 2 alone
suffices in most cases. For simple vectors, steps 1 and 3 are only needed
if the ravel constructed in step 2 has the wrong length.
3.4.5 Construction of arbitrary nested values
The depth of a nested value is recursively defined as:
0, if the value is a simple scalar
1, if the value is a simple vector
N+1, if the value is nested and N is the depth of its deepest ravel element
The monadic APL function ≡ (called Depth) returns the depth of an
APL value.
In the previous chapter we have seen how arbitrary simple values, i.e.
values of depth 0 or 1 are constructed. We can now create a value of depth
N + 1 recursively:
construct the shape vector in the same way as for arbitrary simple values.
construct the ravel of the new value from smaller items such as
integer scalars, integer vectors, character scalars and character vectors,
and items with a depth N or less. Enclose non-simple ravel items (i.e. items
with depth > 1) in parentheses.
reshape the ravel with the shape vector using dyadic ⍴.
Examples:
1 2 3 ⍝ three element vector
1 2 3
⍴1 2 3 ⍝ how many elements?
3
≡1 2 3 ⍝ how deep?
1
1 (2 3) ⍝ two (!) element vector with nested second element
1 2 3
⍴1 (2 3) ⍝ how many elements?
2
≡1 (2 3) ⍝ how deep?
2
1 (2 (3 4)) ⍝ two element vector with nested second element
1 2 3 4
⍴1 (2 (3 4)) ⍝ how many elements?
2
≡1 (2 (3 4)) ⍝ how deep?
3
When the APL interpreter prints nested values it prints extra spaces
around them. These spaces distinguish nested values from their simple
counterparts with the same ravel elements, but makes it rather difficult
to understand values with deeper nesting.
3.4.6 Displaying the structure of values
We have seen in the examples above that that some APL values look the same
(e.g. numeric scalars and numeric vectors) or very similar (nested values
with the same elements in their ravels, like 1 2 3 vs. 1 (2 3) above).
For that reason, APL interpreters that support nested values typically
come with a function called Display that shows the structure of a value
in a clearer way. This function is very useful for analyzing problems that
are caused by different values that look similar:
1 2 3 + 1 2 3 ⍝ add two 3 element vectors
2 4 6
1 2 3 + 1 (2 3) ⍝ add 3 element vector and 2 element vector
LENGTH ERROR
1 2 3+1 (2 3)
^ ^
Since the Display function is of such importance, GNU APL has made it a
built-in function called dyadic ⎕CR. The monadic ⎕CR (character
representation) is a standard function in all APL interpreters that converts
APL values and user defined functions into character strings. The left
argument of dyadic ⎕CR does the same, but its left argument lets you choose
one of several formats. Formats 4 and 8 of ⎕CR select a format that is
very similar to the output of the Display function in other interpreters:
8 ⎕CR 1 ⍝ show structure of scalar 1
1
8 ⎕CR 1 2 3 ⍝ show structure of simple vector 1 2 3
┌→────┐
│1 2 3│
└─────┘
8 ⎕CR 1 (2 3) ⍝ show structure of nested vector 1 (2 3)
┌→──────┐
│1 ┌→──┐│
│ │2 3││
│ └───┘│
└ϵ──────┘
8 ⎕CR 1 (2 (3 4)) ⍝ show structure of nested vector 1 (2 (3 4))
8 ⎕CR is a character matrix constructed according to the following rules:
the matrix consists of a frame (solid line) that surrounds
its content.
The content is created from the ravel elements of the value that are
arranged according to the shape of the value. If a ravel element is a
nested value then that value is displayed with its own frame (and these rules
apply recursively.
The frame can contain additional indicators. If the rank of the value
is ≥ 1 then the horizontal top line of the frame contains information
pertaining to the last dimension of the value. If the rank of the value
is ≥ 2 then the vertical left line of the frame contains information
pertaining to the other dimensions of the value. The horizontal bottom line
of the frame is related to the depth of the ravel.
An arrow (→ on the top line or ↓ on the left line) indicates that the
corresponding dimension(s) are present and non-empty.
An ⊖ on the top line or ⌽ on the left line) indicates that the
corresponding dimension(s) are present but empty. In this case the ravel
has length 0 and instead of the empty ravel the prototype of the value
(a concept explained later on) is shown.
An ∊ on the bottom line indicates that the ravel contains nested elements;
multiple ∊ indicate deeper nesting.
3.4.7 Vector Notation versus Catenation
For beginners the difference between vector notation (a sequence of items
separated by spaces) and catenation (a sequence of items separated by commas)
can be confusing because often, in particular for simple scalars and vectors,
both of them produce the same result:
1 2 3
1 2 3
1,2,3
1 2 3
In the example above, vector notation executes faster because no function
needs to be computed. Sometimes, however, vector notation may produce a
result other than expected:
Vector notation starts with the leftmost item and adds one item for every
space (or group of spaces). If an item added is not a scalar (like (4 5) in
the example above) then the item is automatically converted to a nested
value.
Catenation works differently; in the above example the two vectors 1 2 3 and
(4 5) are simply concatenated to form a vector of length 5.
The parentheses in (4 5) in in the catenation example were redundant, while
the parentheses in the vector notation were not. Once again 8 ⎕CR helped to
clarify the matter.
3.4.8 Scalar Extension
Before continuing we need to introduce a fundamental APL mechanism called
scalar extension. This mechanism is applied in many places.
Almost all built-in APL functions are partial, which means that there are
arguments for which the function returns an error instead of a result. Some
of the very few total (i.e. non-partial) functions are monadic ⍴
and monadic ≡. Typically dyadic functions put more requirements on their
arguments than monadic functions. The reason is that not only must the
individual left and right arguments satisfy some conditions, but the left
and right arguments must also fit each other. For example:
1 2 3 + 1 2 3 ⍝ 1 2 3 is a valid arguments for +
2 4 6
1 2 + 1 2 ⍝ 1 2 is also a valid arguments for +
2 4
1 2 + 1 2 3 ⍝ they cannot be mixed, though
LENGTH ERROR
1 2+1 2 3
^ ^
The most common requirement of dyadic functions is that the left
and right argument have the same shape. The sum of two 3 element vectors
makes sense, while the sum of a 2 element vector and a 3 element vector
does not:
1 2 3 + 4 5 6 ⍝ OK to add two 3 element vectors
5 7 9
1 2 3 + 4 5 ⍝ not OK to add 2 element vector to 3 element vector
LENGTH ERROR
1 2 3+4 5
^ ^
Now scalar extension is an exception to most matching shape requirements.
If one of the arguments of a dyadic function is a scalar, and if the function
supports scalar extension, then the scalar argument is automatically reshaped
to the shape of the other argument. (If both arguments were scalar, then they
have the same shape already and scalar extension would have no noticeable
effect).
1 2 3 + 4 ⍝ OK by virtue of scalar extension of right argument
5 6 7
1 + 4 5 6 ⍝ OK by virtue of scalar extension of left argument
5 6 7
Scalar extension is applied recursively. If some ravel element of a
value A is nested and the corresponding ravel of B is not (or vice
versa) then the non-nested element is scalar extended to the other:
1 2 3 4 + 1 2 3 ⍝ expect length error
LENGTH ERROR
1 2 3 4+1 2 3
^ ^
1 2 (3 4) + 1 2 3 ⍝ 3 is scalar extended to match (3 4)
2 4 6 7
3.4.9 List of Built-in Scalar Functions
The power of APL comes from the large number of built-in functions.
Most of them belong to a category called scalar functions and below is
a list of them. Normally the monadic and the dyadic variants are closely
related and are both scalar functions. An exception is ∼ where the monadic
form is a scalar function while the dyadic form is not.
Dyadic: Z←A FUN B
FUN
Monadic: Z←FUN B
Name/Description
Example(s)
Name/Description
Example(s)
Plus
Z is A plus B
2 + 3
5
+
Conjugate
Z is the complex
conjugate of B
+ 1J42
1J¯42
Minus
Z is A minus B
2 - 3
¯1
-
Negative
Z is the negative of B
- ¯2
2
Times
Z is A times B
2 × 3
6
×
Direction
Z is 1, 0, or ¯1
if B > 0, B = 0, or B < 0 resp.
× ¯5
¯1
Divide
Z is A divided by B
3÷2
1.5
÷
Reciprocal
Z is 1 ÷ B
÷4
0.25
Minimum
Z is the smaller of A and B
2 ⌊ 3
2
⌊
Floor
Z is B rounded down
⌊ 4.7
4
Maximum
Z is the larger of A and B
2 ⌈ 3
3
⌈
Ceiling
Z is B rounded up
⌈ 4.7
5
Power
Z is A raised to
the Bth power
2⋆3
8
⋆
Exponential
Z is e to
the Bth power
⋆1
2.718281828
Logarithm
Z is the logarithm
of B to base A
2⍟8
3
⍟
Natural Logarithm
Z is the natural
logarithm of B
⍟8
2.079441542
Residue
Z is B modulo A
10∣13
3
∣
Magnitude
Z is the magnitude of B
∣3J4
5
Binomial
Z is Γ(1+B) ÷ (Γ(1+A) × Γ(1+B-A))
For integers A≥0 and B≥0:
Z is (B!) ÷ ((A!) × (B-A)!)
3!5 ⍝ aka. 5 over 3
10
!
Factorial
Z is Γ(1+B), aka.
B! for integers B≥0
!4 ⍝ factorial of B
24
Circular Functions
Z is a function, selected
by integer A, and called
with argument B:
And/LCM
For boolean A and B is Z the
logical AND of A and B.
For integer A or B is Z the
least common multiple of A and B
0 0 1 1 ∧ 0 1 0 1
0 0 0 1
∧
N/A
∧ 0 1 0 1
VALENCE ERROR
∧0 1 0 1
^
Or/GCD
For boolean A and B is Z the
logical OR of A and B
For integer A and B is Z the
gratest common divisor of A and B
0 0 1 1 ∨ 0 1 0 1
0 1 1 1
∨
N/A
∨ 0 1 0 1
VALENCE ERROR
∨0 1 0 1
^
Nand
Z is ∼ (A ∧ B)
0 0 1 1 ⍲ 0 1 0 1
1 1 1 0
⍲
N/A
⍲ 0 1 0 1
VALENCE ERROR
⍲0 1 0 1
^
Nor
Z is ∼ (A ∨ B)
0 0 1 1 ⍱ 0 1 0 1
1 0 0 0
⍱
N/A
⍱ 0 1 0 1
VALENCE ERROR
⍱0 1 0 1
^
Equal
Z is 1 for equal A and B,
and 0 otherwise.
1 2 3 = 2
0 1 0
=
N/A
= 0 1 0 1
VALENCE ERROR
=0 1 0 1
^
Less Than
Z is 1 if A is less than B,
and 0 otherwise.
1 2 3 < 2
1 0 0
<
N/A
< 0 1 0 1
VALENCE ERROR
<0 1 0 1
^
Less or Equal
Z is 1 if A s less than or
equal to B, and 0 otherwise
1 2 3 ≤ 2
1 1 0
≤
N/A
≤ 0 1 0 1
VALENCE ERROR
≤0 1 0 1
^
Not Equal
Z is 1 if A differs from B,
and 0 otherwise
1 2 3 ≠ 2
1 0 1
≠
N/A
≠ 0 1 0 1
VALENCE ERROR
≠0 1 0 1
^
Greater or Equal
Z is 1 if A s greater than or
equal to B, and 0 otherwise
1 2 3 ≥ 2
0 1 1
≥
N/A
≥ 0 1 0 1
VALENCE ERROR
≥0 1 0 1
^
Greater Than
Z is 1 if A is greater than B,
and 0 otherwise
1 2 3 > 2
0 0 1
>
N/A
> 0 1 0 1
VALENCE ERROR
>0 1 0 1
^
3.4.10 List of Other Built-in Functions
To have all functions listed in one place, we also provide the
remaining build-in APL functions here. These functions are either
represented by a single APL character, or by a name that starts with ⎕,
followed by one or more letters from A-Z ("quad functions"). There is no
big difference between quad functions and other built-in functions, except
for the name. Often quad functions are used for services of the
underlying operating system, such as time information, user accounting, etc.
Note that the non-quad functions are all defined by the ISO APL standard
(and identical on all APL interpreters), while very few quad-functions
are defined by the standard and the other ones differ considerably between
different APL interpreters.
Note: The table below uses the concept of APL variables which have not
been introduced yet (but will be soon). If you are an APL novice then please
ignore the table for the moment and return to it after variables have been
introduced.
Dyadic: Z←A FUN B
FUN
Monadic: Z←FUN B
Name/Description
Example(s)
Name/Description
Example(s)
Reshape
Z is the ravel of B (possibly shortened or replicated
as needed) with shape A
2 3⍴1 2 3 4 5 6
1 2 3
4 5 6
⍴
Shape
Z is the shape of B
⍴ (2 3 ⍴ 1 2 3 4 5 6)
2 3
Join
Z is the concatenation of A and B
A ← 2 3⍴'abcdef' ◊ B ← 2 3⍴1 2 3 4 5 6
A
abc
def
B
1 2 3
4 5 6
A,B
abc 1 2 3
def 4 5 6
,
⍪
Ravel
,B is the ravel of B (a vector with the same elements as B.
Table
⍪B is a 2-dimensional matrix with the elements of B.)
⎕ ← B ← 2 3 ⍴ 1 2 3 4 5 6
1 2 3
4 5 6
,B
1 2 3 4 5 6
⎕ ← B ← 1 2 3 4 5
1 2 3 4 5
⍪B
1
2
3
4
5
Index of
Z is the positions of B's elements in A
'abcdefgh' ⍳ 'hello'
8 5 9 9 9
⍳
Index Generator
Z is 1 2 ... B
⍳6
1 2 3 4 5 6
Identical
Z is 1 if A and B have the same shape and the same
ravel elements (including identical nested ravel elements), and 0
otherwise.
1 2 3 ≡ 1 2 3 ⍝ same shapes and ravels
1
1 2 3 = 1 2 5 ⍝ for comparison: equal
1 1 0
1 2 3 ≡ 1 2 5 ⍝ same shapes, different ravels
0
1 ≡ ,1 ⍝ same ravel, different shapes
0
≡
Depth
Z is the depth (the level of nesting) of B
≡ 1
0
≡ 1 2 3
1
≡ 1 (2 3) 4
2
Not Identical
Z is 0 if A and B have the same shape and the same
ravel elements (including identical nested ravel elements), and 1
otherwise.
1 2 3 ≢ 1 2 3 ⍝ same shapes and ravels
0
1 2 3 ≠ 1 2 5 ⍝ for comparison: not equal
0 0 1
1 2 3 ≢ 1 2 5 ⍝ same shapes, different ravels
1
1 ≢ ,1 ⍝ same ravel, different shapes
1
≢
Tally
Z is the length of the first axis of B
≢ 1
1
≢ 2 3⍴1 2 3
2
≢ 4 3⍴1 2 3
4
≢ 1 (2 3) 4
3
Member of
Z is a Boolean value with the same shape as A.
The elements of Z indicate if the corresponding element in A is
equal to some element in B.
(2 3⍴1 2 3 4 5 6) ϵ 4 5 6 7 8
0 0 0
1 1 1
∈
Enlist
Z is the elements of B listed in depth-first order (all
nested sub-values of a ravel element come before the
next ravel element at the same level).
∈ (1 2 3) (4 5) 6
1 2 3 4 5 6
Deal
Z is a subset of ⎕IO ... ⎕IO+B containing A elements
chosen at random
3 ? 10
7 9 4
3 ? 10
4 2 10
?
Roll
Z has the same shape as B. The elements of Z are random
numbers between ⎕IO and ⎕IO+b where b is the corresponding
element in B.
? 10 100 1000
5 95 697
Grade Up/Down with collating sequence
A is a character array which defines a sorting order for
characters. B is a character vector (string) to be sorted.
Z is an integer vector such that B[Z] is sorted according to the
sorting order defined by A.
⎕IO←1 ⍝ ⍋ and ⍒ depend on ⎕IO
⊢B←5 4⍴'DEADBADECEDEBEADDEE' ⍝ B: the items to be sorted
DEAD
BADE
CEDE
BEAD
DEED
'ABCDE' ⍋ B ⍝ sort B with A < B < C < D < E
2 4 3 1 5
B['ABCDE' ⍋ B;] ⍝ the sorted items
BADE
BEAD
CEDE
DEAD
DEED
B['CBADE' ⍋ B;] ⍝ same with C < B < A < D < E
CEDE
BADE
BEAD
DEAD
DEED
⍋
⍒
Grade Up/Down
Z is a vector of indices such that B[Z] is ordered
ascendingly (⍋) or descendingly (⍒). In other words, B[⍋B] is B
sorted in ascending order and B[⍒B] is B sorted in descending order.
⍋ B←1 7 4 2 6
1 4 3 5 2
B[⍋B]
1 2 4 6 7
B[⍒B]
7 6 4 2 1
Representation aka. Encode
Z is numbers in B represented in the number system with radices A.
⍴A determines the number of digits in that representation.
2 2 2 2 2 2 ⊤ 42 ⍝ 42 in base 2 (aka. binary) with 6 digits
1 0 1 0 1 0
⊤
N/A
⊤ 42
VALENCE ERROR
⊤42
^
Base Value aka. Decode
Z is the number corresponding to the digits B in the number system
with radices A.
2 ⊥ 1 0 1 0 1 0 ⍝ binary 1 0 1 0 1 0 in decimal
42
⊥
N/A
⊥ 42
VALENCE ERROR
⊥42
^
Union
Z is A , B (with duplicates of A in B removed)
1 2 2 3 'A' ∪ 3 'B' 'C' 'A'
1 2 2 3 ABC
∪
Unique
Z is B with duplicate elements removed
∪ 1 2 3 4 3 5
1 2 3 4 5
Format
Z is B formatted according to A
⊢B←3 2ρ1 .468987 2 57.276 3 27963
1 0.468987
2 57.276
3 27963
⍝ format by specification: (field size + precision)
⍝ precisions < 0 imply exponential format
4 2 12 ¯5 ⍕ B ⍝ field sizes 4 and 12, precisions 2 and ¯5
1.00 4.6899E¯1
2.00 5.7276E1
3.00 2.7963E4
⍝ format by example: (example string A)
⊢B←234.67 456.23 987.65 34.23
234.67 456.23 987.65 34.23
"SUM: $5,555.50" ⍕ +/ B
SUM: $1,712.78
⍕
Format
Z is B for strings; otherwise B converted to a character vector or matrix
N/A
2 ⍎ 42
VALENCE ERROR
2⍎42
^^
⍎
Execute
Z is the result of executing string B as APL expression
Take
Z is a rectangular sub-area of B according to A
Find
Z[i] is 1 if A starts at B[i] in B and 0 if not.
3 4 ⍷ 1 2 3 4 5
0 0 1 0 0
⋸
N/A
⋸ 'abc'
VALENCE ERROR
⍷'abc'
^
Index
Z is B[A]
2 ⌷ 'Hello'
e
⍝ second character
⌷
N/A
⌷ 1 2 3
VALENCE ERROR
⌷1 2 3
^
Right
Z is B.
'Left' ⊢ 'Right'
Right
⊢
Identity
Z is B. ⊢B is a shortcut for ⎕←B
Left
Z is A
'Left' ⊣ 'Right'
Left
⊣
Hide
Z is B as a committed APL value (and is therefore not
automatically displayed). ⊣B is a shortcut for (⍳0)⍴B.
1 + 3
4
⊣ 1 + 3
Partition
Z is B, divided into partitions according to A. Two elements B[b]
and B[b+1] of B belong to the same partition if A[b] ≥ A[b+1] > 0.
Each partition becomes a nested item of Z where B[b] with A[b] = 0
are removed.
1 1 2 2 3 3 3 3 ⊂ 'ABCDEFGH' ⍝ 3 partitions
AB CD EFGH
1 1 0 0 3 3 3 3 ⊂ 'ABCDEFGH' ⍝ 2 partitions
AB EFGH
⊂
Enclose
Z is B for simple scalars, otherwise a scalar
that contains B as a nested value
Intersection
Z is the elements of A that are also in B
1 2 3 4 5 6 ∩ 3 4 5 6 7 8
3 4 5 6
∩
N/A
∩ 3 4 5 6 7 8
VALENCE ERROR
∩3 4 5 6 7 8
^
Compress
Z is the elements of B with B[i] repeated A[i] times
1 2 3 4 5 / 'ABCDE'
ABBCCCDDDDEEEEE
1 2 3 4 5 / '1A' '2B' '3C' '4D' '5E'
1A 2B 2B 3C 3C 3C 4D 4D 4D 4D 5E 5E 5E 5E 5E
/
⌿
N/A (note that f/B is an operator that takes one value argument)
/ 'ABCDE'
SYNTAX ERROR
/'ABCDE'
^
Expand
A[i] is 0 or 1; if 1 then Z[i] is B[i⌷+\A] or ↑0⍴B otherwise.
1 0 1 0 0 1\1 2 3 ⍝ 1 at 1, 2 at 3, and 3 at 6; ↑0⍴B is 0
1 0 2 0 0 3
1 0 1 0 0 1 \ 'ABC' ⍝ A at 1, B at 3, and C at 6; ↑0⍴B is ' '
A B C
\
⍀
N/A (note that f\B is an operator that takes one value argument)
\ 'ABCDE'
SYNTAX ERROR
\'ABCDE'
^
3.4.11 List of Built-in Monadic APL Operators
A monadic APL operator OP1 takes 2 or 3 arguments in the following order:
a left value A (mandatory or optional, depending on the operator),
a mandatory left function argument f (followed by the operator itself)
a mandatory right value B.
Used with 2 Value Arguments A and B: Z←A f OP1 B
OP1
Used with 1 Value Argument B: Z←f OP1 B
Name/Description
Example(s)
Name/Description
Example(s)
Reduce N-wise
Like f/B and f⌿B except that f is applied to groups
C1 C2 ... Cn.
Each group Cn has A consecutive items of B and starts at position
i of the axis along which the N-wise reductions are computed.
⊢R←1 2 3 4 5 6
1 2 3 4 5 6
4 +/ R
10 14 18
+/R[1 2 3 4] ⍝ group C₁ ←→ Z[1]
10
+/R[2 3 4 5] ⍝ group C₂ ←→ Z[2]
14
+/R[3 4 5 6] ⍝ group C₃ ←→ Z[3]
18
⊢R←2 6⍴⍳12 ⍝ ⍴⍴R > 1
1 2 3 4 5 6
7 8 9 10 11 12
4 +/ R
10 14 18
34 38 42
/
⌿
Reduce Z is computed by applying f repeatedly along the last axis
of B, i.e. Z←[;;1] f B[;;2] f ... f B[;;N] (the number of semicolons
is ¯1+⍴⍴B and N←¯1↑⍴B). f⌿B is the same except that f is computed
along the first axis of B.
2 3⍴⍳6 ⍝ example argument B
1 2 3
4 5 6
+/ 2 3⍴⍳6 ⍝ +/ is the sum of row elements
6 15
+⌿ 2 3⍴⍳6 ⍝ +⌿ is the sum of column elements
5 7 9
N/A
2 +\ 1 2 3 4
VALENCE ERROR
2+\1 2 3 4
^ ^
\
⍀
Scan
Z←f\B or Z←f⍀B is like Z←f/B or Z←f⌿B resp. except that the partial
results of the different invocations of function f are not discarded
but included in the result Z.
+\ 1 2 3 4 5 ⍝ 1, 1+2, 1+2+3, 1+2+3+4, 1+2+3+4+5
1 3 6 10 15
Commute
Z is B f A (the arguments A and B are exchanged)
2 ÷ 1
2
2 ÷⍨ 1
0.5
⍨
Z is B f B (the single argument B is duplicated)
×⍨ 1 2 3 4 ⍝ squares
1 4 9 16
Each (dyadic)
Z[i] is A[i] f B[i] (f is called dyadically
for all corresponding items of A and B)
A dyadic APL operator OP2 takes 3 or 4 arguments in the following order:
a left value A (mandatory or optional, depending on the operator),
a mandatory function argument f, (followed by the operator itself)
a mandatory function argument g, and
a mandatory right value B.
Used with 2 Value Arguments A and B: Z←A f OP2 g B
OP2
Used with 1 Value Argument B: Z←f OP2 g B
Name/Description
Example(s)
Name/Description
Example(s)
Inner Product
Z[i;j] is f / A[i] g B[j]. Row A[;j] is multiplied
with column B[i;] and the resulting vector V is
then f-reduced to give the scalar Z[i;j] (enclosed
if necessary to yield a scalar).
For simple numeric matrices A and B this is
the "matrix multiplication" known from linear
algebra.
⊢A←2 2⍴1 2 3 4
1 2
3 4
⊢B←2 2⍴1 2 3 4
1 2
3 4
⊢A +.× B
7 10
15 22
f.g
Monadic f.g throws an error however ⍨ can be used to duplicate B
+.× 2 2⍴1 2 3 4
VALENCE ERROR
+.×2 2⍴1 2 3 4
^ ^
+.×⍨ 2 2⍴1 2 3 4
7 10
15 22
Outer Product
Z[i;j] is A[i] g B[j]. ⍴Z ←→ (⍴A),⍴B)
Rank Z←A f ⍤ y B is
function f applied to the
rank-a cells of A
and the rank-b cells of B
(with a and b defined
by y, see monadic case).
This dyadic case uses
only a and b of
y←m a b; the first item m
is used in the monadic case.
The intention of this somewhat
confusing definition was apparently
the use of the same y
in the monadic and dyadic cases.
However, a two item y←a b
(with a ignored in the monadic
case) would have been more plausible.
0 1 2⌽⍤0 1 'ABC'
ABC
BCA
CAB
⍤
Rank Z←f ⍤ y B is
function f applied
to the rank-m cells
of B (where m is
defined by y, see
below.).
The rank-v cells of
a value V, v≤⍴⍴V,
is V enclosed along its
v lower axes, i.e.
⊂[(-v)↑⍴V] V
Conceptually is y
a 3 item integer vector:
y ← m a b.
Shorter y are expanded:
y←m ←→ y←m m my←a b ←→ y←b a b
This monadic case uses only
the first item m of y,
but not a or b.
y←0 ◊ ⍳⍤y 1 2 3
1 0 0
1 2 0
1 2 3
⍝ ISO standard 13751 uses arrays like N233 below,
⍝ whose items are unique and reflect their position
⍝ in the array That is, e.g. N233[i;j;k] ←→ ijk
⍝
⎕ ← N233 ← 10 ⊥¨ ⍳2 3 3
Power Operator Z←A f ⍣ N B (N > 0):
repeat: Z←B←A f B
(repeats N times).
Z←A f ⍣ N B (N < 0):
repeat: Z←B←A f-1 B
(repeats -N times).
Z←A f ⍣ g B
with function g:
repeat: Z←B←A f B
until (A f B) g B.
2 (×⍣ 5) 1 ⍝ 2 × 2 × 2 × 2 × 2 × 1
32
2 (×⍣ ¯5) 1 ⍝ ((((1 ÷ 2) ÷ 2) ÷ 2) ÷ 2) ÷ 2
0.03125
2 (-⍣≤) 6.4 ⍝ (2 - 6.4) = ¯4.4 and 4.4 ≤ 6.4
¯4.4
⍣
Power Operator Z←f ⍣ N B (N > 0):
repeat: Z←B←f B
(repeats N times).
Z←f ⍣ N B (N < 0):
repeat: Z←B←f-1 B
(repeats -N times).
Z←f ⍣ g B
with function g:
repeat: Z←B←f B
until (f B) g B.
(-⍣3) 5 ⍝ - - - 5
¯5
(-⍣¯3) 5 ⍝ --1 is +
5
Notes: The outer product is considered a dyadic operator here (and also
in the APL standard), even though it has only one functional argument and
not two. If it were a monadic operator then the function argument g would
have to appear left of the operator symbol (.) rather than right of it.
In a way one can consider the outer product as the inner product with '∘'
being the identity function.
The ISO standard defines f⍤y as dyadic operator (with a left (function)
argument f and right (numeric) argument y. y is a numeric vector with
1, 2, or 3 elements, which may be ambiguous in certain cases.
3.4.13 Functions and Operators with Axis Argument
As we have seen above, some built-in functions and operators have variants
that operate along the first or along the last axis. For example:
⊢A←2 3 ⍴'A'
AAA
AAA
⊢B←2 3⍴'b'
bbb
bbb
A,B ⍝ catenate along last axis
AAAbbb
AAAbbb
A⍪B ⍝ catenate along first axis
AAA
AAA
bbb
bbb
For built-in functions and operators the symbol for the variant that
works along the first axis is the symbol for the variant that works along
the last axis but with a '-' overstrike. These days APL uses a keyboard
layout where every APL character can be entered with the help of the
Ctrl-key or with the Alt-key, but in the early days of APL the character
'⍪' was produced by typing ',' then backspace (which moved the input cursor
back over the ',' just typed) and finally '-'. On a standard ASCII terminal
this 3 character sequence would have replaced ',' with '-' but on an APL
terminal it instead would have combined the ',' and the '-' resulting in
the overstrike character '⍪'.
Coming back to our axis arguments topic: Those built-in functions that
can operate along the first or along the last axis can also operate along
any other axis. The desired axis is provided after the function or operator
symbol enclosed in brackets:
The axis can be given as a numeric literal as above, but also as a
variable whose value is a number indicating a valid axis of the arguments.
3.4.14 System Functions
The built-in APL functions that we have introduced so far were represented
by a single APL glyph (UCS character). These functions are commonly referred
to as "primitive APL functions" (or operators) or simply "APL primitives".
There is another group of built-in APL functions called "System Functions"
which are used in the same way as primitives. The distinction between APL
primitives and system functions is somewhat arbitrary and not only result
from a lack of suitable APL glyphs or keyboard keys but allow an arbitrary
number to be defined. The few differences between primitives and system
functions are:
a primitive is denoted by a single UCS character while a system function
is denoted by the character ⎕ followed by one or more characters A-Z
or a-z (see chapter "Names of System Functions and System Variables"
above)
The function computed by APL primitives is essentially the same on
different APL interpreters while the system functions (especially
their presence or absence) may differ considerably between different
APL interpreters.
APL primitives compute APL values from other APL values while system
functions typically provide an interface to the resources of the
underlying operating system on which the interpreter runs.
For a quick tour of GNU APL the details of the GNU APL system functions
are far to extensive and we refer the reader to the GNU APL info manual
where the GNU APL specific system functions are described in more detail,
and to the ISO standard 13751 for more common system functions. Note that
some system functions are obsolete these days but maintained only for
backward-compatibility with older (i.e. APL1) interpreters.
3.4.14.1 Z ← ⎕AF B : Atomic Function
Monadic, obsolete. In a pure Unicode interpreter like GNU APL ⎕AF B
seems to be the same as ⎕UCS B.
3.4.14.2 Z ← A ⎕AT B : Attributes
Dyadic: For a (user-defined) name FOO which designates an existing
defined function or variable, the expression A ⎕AT 'FOO' yields a
numeric vector with attributes from a category that is defined by A:
A=1: result type, function and operator valences
A=2: creation time, valences
A=3: execution properties
A=4: object sizes (CDR)
Note that the name FOO is quoted to make it a character vector. ⎕AT also
accepts a character matrix if the attributes of multiple names shall be
obtained.
3.4.14.3 Z ← A ⎕CR B : Character Representation
Monadic: For a (user-defined) name FOO which designates an existing
defined function or operator, the expression ⎕CR 'FOO' yields the
character representation for that name. The character representation of a
function is a character matrix with one line for every line (including
the header line) of the function or operator.
Dyadic: As a GNU APL specific feature, dyadic A ⎕CR 'FOO' is one of
over 40 different conversion functions. The integer scalar A ≥ 0 selects
one of these functions. ⎕CR ⍬ and ⎕CR '' display slightly different
lists of the functions implemented so far.
3.4.14.4 Z ← ⎕DL B : Delay
Monadic: ⎕DL N pauses the operation of the interpreter for N seconds.
3.4.14.5 Z ← A ⎕DLX B : Donald Knuth's Dancing Links
Dyadic: ⎕DLX implements a powerful backtracking machine known as
"Dancing links" or "Algorithm X". The algorithm was published by Donald
Knuth in 2000 and is the algorithm of choice for a class of problems that
is best soved by means of backtracking. For example the 8 tower and 8
queens problem on a chess-board or sudokus. Formally ⎕DLX solves
the so-called "exact cover problem": given a binary matrix B, find a
subset Z of ⍳↑⍴B so that (+/[1]B[Z;]) ≡ ((¯1↑⍴B)⍴1). Less formally:
find a sub-matrix S←B[Z;] of B so that every column of S contains
exactly one 1. The left argument A of A ⎕DLX B controls the type
of result desired such as compute only one solution, compute all solutions,
etc.
3.4.14.6 Z ← A ⎕EA B : Execute Alternate
Dyadic: A ⎕EA B computes ⍎B and, if that fails, computes ⍎A.
A and B are character vectors containing APL expressions. The result of
A ⎕EA B is the result of ⍎A if it succeeds, otherwise the result of
⍎B. If ⍎B succeeds then ⍎A is not computed so that either
⍎B or ⍎A is being computed.
3.4.14.7 Z ← A ⎕EB B : Execute Both
Dyadic: A ⎕EB B computes ⍎B and then ⍎A. Errors in ⍎B
are ignored, so that ⍎B and ⍎A are both computed. Typically
⍎A is an error handler for the case where ⍎B has failed, e.g.
for providing a replacement for the missing result of ⍎A.
⎕EB is a GNU APL specific feature.
3.4.14.8 Z ← ⎕EC B : Execute Controlled
Monadic: ⎕EC B computes ⍎B but does not interupt the APL
interpreter when an error occurs. Instead the 3-element result vector
(Z1 Z2 Z3)←⎕EC B indicates the type of result:
Z1=0: Error, e.g. 2+'A'
Z1=1: Value, e.g. 2+2
Z1=2: Committed Value, e.g. A←2+2
Z1=3: No Value, e.g. FOO with FOO returning no result
Z1=4: Branch, e.g. → 2
Z1=5: Escape, e.g. →
Z2 is the result that ⎕ET (see below) would have had if ⍎B
were computed without ⎕EC. When computed with ⎕EC then ⎕ET
is not affected.
Z3 is the actual result of ⍎B:
Z1=0: ⎕EM (see below)
Z1=1: e.g. 4 for 2+2
Z1=2: e.g. 4 for A←2+2
Z1=3: 0 0⍴0
Z1=4: e.g. 2 for → 2
Z1=5: 0 0⍴0
3.4.14.9 Z ← ⎕ENV B : ENvironment Variables
Monadic: GNU APL feature: return the names and values of the environment
variables in the operating system at the point in time when the GNU APL
interpreter was started. The argument B of ⎕ENV B is a prefix
for the names of the environment variables that shall be returned.
3.4.14.10 Z ← A ⎕ES B : Event Simulate
Nomadic: Programmatically simulate an error event. For testing error
handlers. Monadic ⎕ES B is ⎕EM ⎕ES B or B ⎕ES ⎕ET depending
on B being either a character vector (event message) or a 2-item integer
vector (event type).
3.4.14.11 Z ← ⎕EX B : EXpunge
Monadic: Argument B of ⎕EX B specifies one or more name(s) of
variables, functions, or operators that shall be erased. For each name, the
corresponding result item is 1 on success or 0 on error.
3.4.14.12 Z ← A ⎕FFT B : Fast Fourier Transform
Nomadic. Compute the fast fourier transform of real or complex B.
The optional argument A controls details such as a window function
to be used for the FFT.
3.4.14.13 ⎕FIO[X] B : File I/O functions
Dyadic: Similar to A ⎕CR B above, A ⎕FIO B is a collection of
over 60 different (sub-) functions. Dyadic A ⎕FIO B has a mandatory
axis argument X which is an integer scalar X ≥ 0 that selects
one of these sub-functions. The sub-function ⎕FIO[X] is then monadic,
dyadic or nomadic.
As a matter of convenience, the functions A ⎕FIO ⍬ and A ⎕FIO ""
(i.e. without an axis argument) display lists of the functions implemented
by A ⎕FIO[X] B so far in different formats.
The functions in ⎕CR are conversion functions which means that they
transform one APL value into another APL value. As a consequence each
conversion function is monadic and the left argument B is the value
that is being converted.
In contrast, the functions in ⎕FIO constitue an interface to the
underlying operating system and every function in ⎕FIO corresponds
to a C function in library libc. This has two consequences:
the corresponding C function in libc has more often than not two or
more arguments. For this reason, the function number which selects
the individual function is now the numeric axis argument X
of A ⎕FIO[X] B.
the now unused left argument A has now become avaiable as another
argument for the selected function ⎕FIO[X]. That is, all functions
A ⎕CR are monadic while most functions ⎕FIO[X] are dyadic.
In the early days of GNU APL there were only a few functions ⎕FIO[X]
and distinguishing different sub-functions by means of function numbers
was already common practice (see, for example, ⎕AT above) and was adequate
as long as the number of sub-functions was small. Over the years, however,
more and more functions were added to ⎕FIO, and the resulting
APL code became more and more difficult to read. Therefore at
some point in time a second mechanism - function names instead of function
numbers - was added. One could now, for example, write ⎕FIO['fopen']
instead of the less intuitive ⎕FIO[3].
A minor flaw of the new function names was that they needed to be quoted.
This led to a third syntax variant where the function name became an
(unquoted) APL name instead of a (quoted) APL string. This is most likely
the final and most elegant syntax for ⎕FIO where one can now write
⎕FIO.fopen instead of ⎕FIO['fopen'] or ⎕FIO[3].
3.4.14.14 Z ← ⎕FX B : FiX
Monadic: B is either a character matrix or a vector of function lines
(function header and APL code). ⎕FX B creates a new defined APL function
(see the chapter "Defined Functions" below). With monadic ⎕FX one can therefore
create new defined APL functions at runtime.
Dyadic: As a GNU APL feature one cannot only create defined functions that
consist of lines of APL code, but also defined functions that were written
in other computer languages, most commonly in C/C++. These so-called
"native" functions are provided in terms of shared libraries that the user
must construct beforehand. In A ⎕FX BA is the file name of a
shared library file and B the APL name of the function implemented
in the shared library.
GNU APL is shipped with a set of templates for creating native functions
or operators that are intended as starting points for native functions
created by the user.
3.4.14.15 Z ← ⎕GTK B : Gtk GUI
⎕GTK is an interface to GTK (Graphical Tool Kit) version 3. It implements
a small subset of the GTK 3 API and is intended for (and limited to)
creating simple windows on the screen, for example to request input from
the user in a more intuitive way than the old-fsshioned ⎕ and ⍞ input
variables.
3.4.14.16 Z ← A ⎕JSON B : JSON parser
Monadic: B is a text string in JSON (JavaScript Object Notation) format
which is converted to the corresponding APL value Z.
Dyadic: B is an APL value which is converted to the corresponding JSON
string. A controls some aspect of this conversion, for example to read
the JSON data string from a file rather than from an APL text vector.
3.4.14.17 Z ← A ⎕MAP B : MAP (replace) ravel elements
Z is B but with every occurance of ravel A[j;1] replaced
with A[j;2].
The same can be achieved with ⎕RE, but ⎕MAP is optimized for this
kind of 1:1 replacement while ⎕RE is more powerful but slower.
3.4.14.18 Z ← ⎕INP B : INPut from script
⎕INP is an early attempt to handle multi-line literals in GNU APL.
It has been obsoleted by GNU APL multi-line literals but is still used
internally. ⎕INP should not be used in ordinary APL programs.
3.4.14.19 Z ← ⎕NA B : Name Association
Obsolete. Throws a "NOT YET IMPLEMENTED" exception when called. This function
ony exists so that workspaces from IBM APL2 that use it can be imported into
GNU APL.
3.4.14.20 Z ← ⎕NC B : Name Class
B is a matrix of APL names and Z is the current category for every
name:
¯1: name B is not a valid APL name (i.e. B is malformed)
0: name B is a valid APL name but not used
1: name B denotes a label (in a defined function)
2: name B denotes a variable
3: name B denotes a defined function
4: name B denotes a defined operator
5: name B denotes a system variable (NOTE: only in GNU APL)
6: name B denotes a system function (NOTE: only in GNU APL)
3.4.14.21 Z ← A ⎕NL B : Name List
Z is a matrix of all (user-defined) names where: every name begins with
an APL string A and has one of the name classes in numeric vector B.
3.4.14.22 Z ← A ⎕PLOT B : Plot a Value
Monadic: Simple plot (without attributes). The value B is plotted
(i.e. displayed in a separate window) with default parameters for colors,
line and point sizes, etc.
Dyadic: Simple plot (with attributes). The value B is plotted with
user-defined attributes in A.
3.4.14.23 Z ← A ⎕PNG B : Process PNG files and Pixel Images
Monadic:
Z ← ⎕PNG B with string B: Convert PNG file B into an array of color planes.
monochrome images have one color plane while RGB images have 3 color planes
(red, green, and blue). All images may have an additional opacity plane
(aka. alpha channel).
Z[;y;x] is the pixel at position (x, y) in the images, x counting from
left to right and y from top to bottom.
Z[1;;] is the gray plane for monochrome (grayscale) images and the red
plane for RGB or RGBA images.
Z[2;;] is the alpha channel for monochrome (grayscale) images with alpha
channel and the green plane for RGB or RGBA images (unless 2 < ↑⍴Z).
Z[3;;] is the blue plane for RGB or RGBA image (unless 3 < ↑⍴Z).
Z[4;;] is the alpha channel RGBA images (unless 4 < ↑⍴Z).
Z ← ⎕PNG B 3-dimensional array as returned above: Display the pixel array
B in a window on the screen.
Dyadic:
Z ← A ⎕PNG B : Write pixel array B to file named A.
3.4.14.24 Z ← A ⎕RE B : Regular expression
Dyadic: Z is B processed according to regular expression A.
⎕RE is an interface to libpcre (where pcre stands for
Perl-compatible regular expression) and the format of A is described
in the different man pages shipped with libpcre.
3.4.14.25 Z ← A ⎕RVAL B : Random APL value
APL provides the primitive ? B which returns an array of (pseudo-)
random integers. A ⎕RVAL B generalizes this concept by computing
(pseudo-) random APL values instead of pseudo-random integers. That
means that not only the raw items of Z but also the shape, depth, and
types of the random values is chosen at random.
Monadic: ⎕RVAL B produces the next random value.
Dyadic: A ⎕RVAL B controls the parameters (probablities) for subsequent
calls of monadic ⎕RVAL B. The numeric scalar A specifies which
parameter shall be specified:
A=0: change the random number generator state
A=1: change the probabilities for ranks
A=2: change the probabilities for shapes
A=3: change the probabilities for types (character/integer/real/complex)
A=4: change the probabilities for depths
The current settings can be obtained by calling A ⎕RVAL B with B
a null vector (e.g., 0 ⎕RVAL ⍬).
3.4.14.26 Z ← [A] ⎕SI B : State Indicator
Return components of the State Indicator (see command )SI below) according
to B:
⎕SI 1: The name of the context. This is either the name of a defined
function, or '◊' for an immediate execution context, or '⍎' for an execute
context
⎕SI 2: The line number of a defined function, or 0 for immediate
execution and execute contexts.
⎕SI 3: funcion name and the line number in square brackets
⎕SI 4: like 3 but augmented like for command )SIS below.
⎕SI 5: The program counter (= token number) in the function.
⎕SI 6: The numeric parse mode
The optional left argument A is an integer scalar that selects one level of
the )SI stack; if omitted then Z contains all levels of the )SI stack.
3.4.14.27 Z ← ⎕SQL[CMD] B : SQL functions
⎕SQL an interface to a SQL database. See info apl for details.
3.4.14.28 Z ← ⎕SVC B : Shared Variable Control
Obsolete. Shared variables are an ancient communication concept from the
mainframe era. They are, to some extent, supported by GNU APL for
compatibility with IBM APL2. "Normal" APL variables are assigned and referenced
by the same APL interpreter instance (i.e. process). In contrast, Shared
variables are assigned and referenced by different processes, making each
shared variable a communication link between the processes.
In GNU APL the system function ⎕FIO provides communication channels that are
simpler to use than shared variables. For that reason, the system functions and
variables related to shared variables are not described in detail here. Users
who need them (to run ancient workspaces) supposedly know how they work,
and users who don't should avoid them.
3.4.14.29 Z ← ⎕SVO B : Shared Variable Offer
Obsolete. See ⎕SVC above.
3.4.14.30 Z ← ⎕SVQ B : Shared Variable Query
Obsolete. See ⎕SVC above.
3.4.14.31 Z ← ⎕SVR B : Shared Variable Retraction
Obsolete. See ⎕SVC above.
3.4.14.32 Z ← ⎕SVS B : Shared Variable State
Obsolete. See ⎕SVC above.
3.4.14.33 Z ← [A] ⎕STOP B : STOP vector
B is a simple string with the name of a defined function.
Z is the stop vector for that defined function.
if A is omitted then the stop vector for defined function B is
returned. Otherwise the stop vector for the defined function is set to A.
Setting the stop vector creates breakpoints at the lines in A. When such a
breakpoint is reached then APL execution stops and a new immediate execution
context is entered. The user can then examine and/or change variables,
terminate or continue the APL execution with →, execute comands, etc.
3.4.14.34 Z ← A ⎕TF B : Transfer Form
⎕TF converts an object in the current workspace into an APL string (and vice
versa).
The integer scalar A selects the format for the result Z; A←1
produces the migration transfer form while A←2 produces the
extended transfer form of an object.
String B is the name of an object (i.e. a variable, defined function,
or (with A←2) a defined operator) in the current workspace.
Z is a string which is a text encoding of the object that can be stored in
files, transferred over a network, etc. and that can be converted back to an
identical object in some other workspace.
The migration transfer form can only be used for old APL1 (aka. ISO standard
8485) functions and variables because it does not support APL2 (aka. ISO
standard 13751) extensions, in particular not: mixed values, nested values,
and defined operators. The format uses fixed size records of 80 bytes each,
which makes it compatible with standard 80 column Hollerith punch cards
(the now obsolete but previously prevalent storage medium for APL workspaces
in the 1960s when APL was invented). For example:
)CLEAR
CLEAR WS
∇Z←A FOO B
Z←1 2 3
∇
1 ⎕TF 'FOO' ⍝ the migration transfer form of defined function FOO
FFOO 2 2 9 Z←A FOO BZ←1 2 3
In contrast, the extended transfer form supports these APL2 extensions. It
uses strings of APL code (primarily APL literals, ⎕FX for defined functions
and operators, and ← for variables). For example:
)CLEAR
CLEAR WS
∇Z←A FOO B
Z←1 (2 3) 'Hello' ⍝ nested and mixed
∇
2 ⎕TF 'FOO' ⍝ the extended transfer form of defined function FOO
⎕FX 'Z←A FOO B' 'Z←1 (2 3) ''Hello'' ⍝ nested and mixed'
If the string B is the result Z of some prior ⎕TF conversion, then
A ⎕TF B creates the corresponding object in the current workspace and Z is
the name of the object created (or '' if an error occurred).
3.4.14.35 Z ← ⎕XML B : XML parser
⎕XML provides a set of functions for parsing XML documents and to extract the
data contained in them. See info apl for details.
3.4.14.36 Z ← ⎕TRACE B : TRACE vector
⎕TRACE is similar to ⎕STOP above. The difference is that ⎕STOP stops the
execution when it hits a breakpoint while ⎕TRACE merely generates a printout
when it hits a breakpoint.
3.4.14.37 Z ← ⎕UCS B : Universal Char Set
⎕UCS converts APL characters to APL integers (with the codepoint of the
character), and vice versa. B can be a mix of characters and the direction
of the conversion is determined by the type of the item. Example:
⎕UCS 'Hello ', 119 111 114 108 100
72 101 108 108 111 32 world
3.5 Variables
Like most computer languages, APL has variables. Unlike compiled computer
languages, variables in APL need not be declared beforehand. Instead,
variables are simply created by assigning a value to a name:
VAR ← 1 2 3
If the name is in use for something other than a variable (for instance, a
defined function), then a VALUE ERROR will be raised. After a value has been
assigned to a name (and, as a side effect of that assignment, a variable with
that name has been created) referring to the name returns the most recent
value that was assigned to the variable:
VAR
1 2 3
VAR ← 1 2 3 4 ⍝ assignment to name VAR
VAR ⍝ reference of name VAR
1 2 3 4
In the above examples a fundamental APL rule should be explained. Normally
a value being computed, for example a constant or the result of a function,
is displayed on the screen. If, however, the value is assigned to a variable,
then it becomes a committed value which is not displayed. The value is
not consumed by the assignment, so that it can be assigned to several variables
in one go:
V1 ← V2 ← 1 2 3
V1
1 2 3
V2
1 2 3
The lifetime of a variable (though not the lifetime of their value which can
change over time) is normally infinite; such variables are called
global variables. There exist also local variables whose lifetime
begins when a defined function is called and ends when that function call
returns a result. This will be explained together with user defined functions).
The lifetime of a variable can be explicitly terminated by either the
command )ERASE or the APL function ⎕EX (expunge):
V1
1 2 3
)ERASE V1
V1
VALUE ERROR
V1
^
V2
1 2 3
⎕EX 'V2'
1
V2
VALUE ERROR
V2
^
The result 1 of ⎕EX indicates successful erasure of the variable. Note
that the argument of ⎕EX is not the variable V2 but a character vector
'V2' containing the name of the variable.
3.5.1 The Variables ⎕ and ⍞
There are two important system variables, ⎕ (quad) and ⍞ (quote quad),
that are used because of their side effects. They are probably the most
frequently used system variables in APL programs.
3.5.1.1 Input and Output with ⍞
When a value is assigned to ⍞ then the value is displayed on the screen:
⍞ ← 1 + 2 ⍝ compute 1 + 2 and display the result
3
In the example above the ⍞ ← is redundant, because the result 3
is not a committed value and would therefore have been displayed anyway.
However, ⍞ ← is most useful to display committed values and temporary
values inside APL expressions, often for debugging purposes.
When ⍞ is referenced, then a line of input is read from the keyboard (actually
from stdin which is normally the keyboard) and the characters read,
excluding the end of line character. The result of referencing ⍞ is always
a character vector (the user input is quoted by ⍞, which may explain
its name quote quad).
INPUT ← ⍞ ⍝ quote-quad input
what we type
INPUT
what we type
An important special case arises when the assignment of a value to ⍞ (but
not ⎕) is immediately (i.e. without another input or output operation)
followed by a reference of ⍞. In that case the terminating end-of-line
character is suppressed and the input requested on the same line:
⍞←"ENTER AMOUNT: " ◊ AMOUNT ← ⍞
ENTER AMOUNT: 42
AMOUNT
42
This special case is often used in interactive APL programs to print a prompt
that tells the user what shall be entered. If this is not desired, then you
can use ⎕ instead of ⍞ in the first assignment:
⎕←"ENTER AMOUNT: " ◊ AMOUNT ← ⍞
ENTER AMOUNT:
42
AMOUNT
42
3.5.1.2 Input and Output with ⎕
When a value is assigned to ⎕ then the value is displayed like for ⍞.
However, the terminating end of line character is always printed, so that
⎕ cannot display a prompt on the same line as the user input in the way
described for ⍞.
Reference to ⎕ differs from referencing ⍞ in two ways:
⎕ displays its own prompt ⎕: on a separate line, and
⎕ evaluates the input line as an APL expression, rather than quoting
it automatically like ⍞ does. The evaluation may produce an error if the
input entered is not a valid APL expression.
The following examples may help explain the referencing of ⎕.
Example 1: The user references ⎕ and assigns the result to a variable
named INPUT:
INPUT ← ⎕
⎕:
After the ⎕: prompt, the user enters the (valid) APL expression 1 + 2
which evaluates to 3:
1 + 2
INPUT
3
Example 2: Like before, the user references ⎕ and assigns the result to a
variable named INPUT:
INPUT ← ⎕
⎕:
After the ⎕: prompt, the user enters the (valid, since quoted) APL string
'Hello' which evaluates to the character vector Hello:
'Hello'
INPUT
Hello
Example 3: Like before, the user references ⎕ and assigns the result to
a variable named INPUT:
INPUT ← ⎕
⎕:
After the ⎕: prompt, the user enters the (invalid, since not quoted) Hello.
Hello is now an APL name as opposed to an APL string as in example 2.
If a variable or niladic function with name Hello were defined, then its
value would be assigned to a variable named INPUT. In our example, however,
this is not the case and therefore a VALUE ERROR is raised:
Hello
VALUE ERROR
Hello
^
3.5.1.3 ⎕ Input in Application Programs
Input by means of ⎕ can be very powerful while writing and debugging APL
programs. It should be avoided, however, in finished application programs.
The reason is that ⎕ throws an error when the user enters something that
is not a valid APL expression. In contrast, input by means of ⍞ does not
throw errors and is therefore safer to use in application programs.
3.6 Indexing
Most programming languages provide indexing which either references or allows
updating a part of the value. Most often, however, indexing is restricted
to a single item. In APL, indexing is much more powerful and can even be
used to create larger APL values than the indexed value.
An index expression, or index, is a sequence of one or more
non-negative simple integers. The sequence is enclosed in brackets and the
components of the sequence are separated by semicolons (unless there is only
one component):
[1;2 3]
The example above shows an index with 2 components 1 and 2 3. An index cannot
be used on its own, but is always bound to the value on its left. The value
left of an index is then said to be indexed by the index expression. The
semantics of indexing a value is that a subset of the ravel of the value
is being selected. This subset is then either referenced (copied) or
changed (assigned) depending on whether the indexed value appears on the
left of an assignment arrow ← or not. We call a value that is being assigned
an lvalue (for left value).
The index is most strongly bound to the value on its left, which causes
indexing of the value to be performed as soon as the value is available.
If the value is an lvalue (only named lvalues can be assigned) then the
lvalue is updated with some other value; otherwise the value is referenced.
Often the item left of the index is a variable and then it looks as if parts
the variable are updated or referenced:
V←1 2 3 4 ⍝ create a variable
V[2 3] ⍝ indexed reference
2 3
V[2 3]←'x' ⍝ indexed assignment
V ⍝ show result of indexed assignment
1 xx 4
What happens behind the scene, however, is that the variable V in the above
examples is resolved into a value (indexed reference) or into an lvalue
(indexed assignment). The value or lvalue is then being indexed.
For indexing to be successful, the index must satisfy certain conditions:
The number of components in the index (i.e. the number of semicolons + 1)
must be equal to the rank of the index
The ith component in the index must be an integer between 1 and the
ith component of the shape of the value that is being indexed.
As a consequence of the first condition, scalars cannot be indexed
(an index without semicolons would require a rank of 1 for the indexed value).
The second condition ensures that the corresponding index components do not
exceed the corresponding shape components. As a C programmer or mathematician
you will find it more natural if the range of an index starts at 0 rather than
1. In APL this can be achieved by setting the system variable ⎕IO (index
origin) to 0:
⎕IO←0
(1 2 3 4)[2]
3
⎕IO←1
(1 2 3 4)[2]
2
Use of ⎕IO←0 should be minimized, however, because most APL programmers assume
the default value of 1 for ⎕IO and the readability of your code may suffer.
An indexed assignment has the side effect of changing parts of the variable,
but the result of it is the value that is assigned, i.e. the right side
of the assignment. The result is not displayed. In that respect, indexed
assignment behaves like non-indexed assignment.
V←1 2 3 4
V[3 3 3⍴2]←'X'
V
1 X 3 4
The example above does not make much sense because the same index 2 is
assigned 27 times. We used it to show the difference between indexed
reference below.
An indexed reference of a variable or value has a result whose shape is
the concatenated shape of the index. This can be used to create values that
are bigger than the indexed value:
Indexing is one of the essential operations of APL programming and fully
understanding it is key to understanding APL. Therefore we summarize the
rules governing indexed assignment and indexed reference:
Common Requirements on Z ← A[X1;...;XN] and
A[X1;...;XN] ← B
A has rank N > 0 (and there are N-1 ≥ 0 semicolons inside the brackets).
Each Xi is a non-nested integer value of arbitrary shape.
For every integer I in the ravel of Xi: ⎕IO ≤ I < ⎕IO + (⍴A)[i]).
Indexed Assignment A[X1;...;XN] ← B
A must be a named value, i.e. an APL variable.
The result of an indexed assignment is B; as a side effect, selected
items in the ravel of A are updated with corresponding items in the
ravel of B.
The result is a committed value (and is therefore not displayed).
If B is a scalar then it is scalar extended according to
X1, ..., XN.
Repeated values in some Xi are valid, but the assignment is
implementation dependent (unless the corresponding items in B are
identical).
The shape of B can have trivial dimensions (dimensions of length 1). Such
dimensions are ignored. The length of any non-trivial dimension (⍴B)[i]
must match the number of elements ⍴,Xi in the corresponding index
item Xi.
Indexed Reference Z ← A[X1;...;XN]
The rank of the result, i.e. ⍴⍴Z, is the sum of the ranks of items
in the index list: ⍴⍴Z ↔ (⍴⍴Z1) + ... + (⍴⍴ZN)
The shape of the result is the catenation of items in the index
list: ⍴Z ↔ (⍴Z1), ..., (⍴XN)
A special case of an index item is the "elided index". If no value is given
between two brackets or semicolons, then this means that the entire dimension
(and not, as you might assume, nothing) is selected by the index item:
A←3 4 ⍴ 1 2 3 4 5 6 7 8 9 10 11 12
A
1 2 3 4
5 6 7 8
9 10 11 12
A[2;] ⍝ elided index for last dimension, i.e. an entire "row"
5 6 7 8
A[;2] ⍝ elided index for first dimension, i.e. an entire "column"
2 6 10
A final example shows the effect of multiple items in different dimensions:
A disadvantage of APL bracket indexing is that while the shapes of the index
items can be freely chosen, the number of semicolons (and therefore the rank
of A) is fixed. That makes it impossible to write functions that cope with
arbitrary ranks of A.
For that reason, a dyadic function X⌷A (called index) is provided where
X plays the role of X1;...;XN in bracket index. X is a
(typically nested) vector of length N and both reference (Z←X⌷A) and
assignment (X⌷A)←B are possible. Unlike bracket index, scalars can be
indexed with the index function (X then has length 0), but elided indices
are not supported by the index function.
3.7 Execution of APL Statements
APL statements are either entered in immediate execution mode, or else
as the body lines of user defined functions.
An APL statement starts out as a sequence of characters other than the
statement separator ◊ (which, as the name suggests, separates different
statements on the same line) and the end of line character (linefeed).
The examples provided above were APL statements.
An example of a line with 3 statements (and no output) is this:
A←1 ◊ B←2 ◊ C←3
The first thing the APL interpreter does when a statement is entered
is to convert the characters of the statement into an internal format
called tokens. The translation of a sequence of characters into a sequence
of tokens, commonly called lexical analysis or tokenization,
can lead to errors when characters are encountered that do not have
meaning in APL:
The rules for tokenizing the input characters are relatively simple:
APL literals are converted to a token that contains the APL value
represented by the literal (as discussed in previous chapters)
APL names are converted to a token that contains the name
(as discussed in previous chapters)
All other characters are converted to a token representing that character
Tokenization is done because operation at the character level is relatively
inefficient, while the internal token format can be parsed more efficiently.
In compiled languages tokenization and parsing are both performed by the
compiler and the efficiency of the internal representation is not relevant
to the efficiency of the executable program. APL is interpreted, however,
so part of the parsing is performed at runtime and the purpose of tokenization
is to perform as much analysis of a statement as possible when the statement
is entered rather than later (and possibly repeatedly) when the statement
is executed.
As an example, the statement:
VARIABLE←1 2 'Hello' (2 'world')
is converted into 3 tokens:
This is possible because the somewhat complicated looking value
1 2 'Hello' (2 'world') is entirely comprized of APL literals
which, unless preempted by a higher token binding precedence (see that
discussion below), can be collapsed into a single (here nested) value
at tokenization time. On the other hand, if there are non-literals
(such as functions or names) between the APL literals, then the literals
left or right of the non-literals cannot be combined and therefore
show up in different tokens:
VARIABLE←1 2 ⍴ 'Hello' (2 'world')
In immediate execution mode, the token sequence created by the tokenization
of the input line is immediately executed, and there appears to be no
difference between tokenization time and execution time. With user defined
functions, however, it pays off to separate lexical analysis from parsing at
execution time. The token sequence for the statement is then stored until it
is executed.
Conceptually, the first step when a statement is executed is to group (also
called "bind") certain tokens to other tokens. APL has no operator precedence
like other languages (the large number of built-in functions and operators
in APL would have made that essentially unmanageable). However, the binding of
tokens plays a similar role. Unfortunately the ISO standard fails to mention
the rules for token binding, but we can refer to the descriptions of commercial
APL vendors. According to those descriptions the binding of tokens has the
following precedence (from strongest binding to weakest binding):
bracket index to the token on its left
assignment arrow to the token on its left
dyadic operator to its right operand (the function on its right)
items in vector notation
operator to its left operand (the function on its left)
function to its left argument (the value on its left)
function to its right argument (the value on its right)
assignment arrow to the token on its right
When we refer to, for example, a "token on its left", then this means when
the token becomes available. In the following example:
(2 × 1 2 3 4)[2]
4
the bracket index [2] has the strongest binding. Before that binding can
take place, however, the expression in parentheses, (2 × 1 2 3 4), must
have been evaluated (yielding 2 4 6 8). The vector 2 4 6 8 is then indexed by
bracket index [2] to give the final result 4.
You may also wonder why operators bind to their operand but not to their
arguments. The reason is that:
when a dyadic operator binds to its right operand, then the bound dyadic
operator has become a monadic operator.
when a monadic operator (or a bound dyadic operator) binds to its left
operand, then the bound monadic operator has become a function.
the bound monadic operator, then binds to its left and right arguments like
every other dyadic or monadic function.
Note also that the actual number of binding strengths is smaller than the list
above might suggest. This is because some bindings are not in conflict with
each other. For example, vector notation binds two or more values to each
other, while the next lower binding strength binds an operator to a function.
These two bindings could have been given the same binding strength.
Some bindings merely define the order in which things are evaluated while
others produce an intermediate result. For example, the binding of a dyadic
function to its left argument forces a left argument in parentheses to be
evaluated first and then the result to be passed to the dyadic function.
On the other hand, the binding of a bracket index to the value or lvalue
on its left forces immediate computation of the bracket index as described
above.
After binding the token, the evaluation of APL statements is performed
according to the "golden rule" of APL:
The rightmost function whose argument(s) are available is evaluated
first.
The function and its argument(s) are then replaced by the result
returned by the function, which causes the arguments of other functions
to become available.
In short this means that APL statements are evaluated from right to left.
Another consequence is that parentheses around the right argument of a
function have no effect, while parentheses around the left argument make
a difference:
(1 + 2) × (3 + 4) ⍝ 3 × 7
21
(1 + 2) × 3 + 4 ⍝ 3 × 7
21
1 + 2 × (3 + 4) ⍝ 1 + (2 × 7)
15
1 + 2 × 3 + 4 ⍝ 1 + (2 × 7)
15
3.8 Defined Functions
Programming in APL is primarily concerned with the creation and testing of
user defined functions. The immediate execution mode used so far is helpful
to try things out, but not for larger applications.
For the sake of explanation we define a user defined function to be a
non-empty sequence of function lines numbered 0, 1, .... The first
line is called function header and determines the following properties of
the function:
if the function returns a value or not
the valence (number of value arguments): niladic, monadic, or dyadic
the name of the function or operator
the number of function arguments: none (normal function),
1 (monadic operator), or 2 (dyadic operator)
the optional axis of the function or monadic operator
the names of local variables of the function
3.8.1 Function Header
The header line of a user defined function consists of several APL names
interleaved with some of the characters ←, (, ), [, ], and ;.
The names can be freely chosen by the user; we will use the names
Z, A, LO, F, X, B, RO, C, and D in our examples with the following meaning:
Z: the name of the result
A: the left value argument
LO: the left function argument of an operator
RO: the right function argument of a dyadic operator
F: the name of the function
X: the axis argument
B: the right value argument
C: the first local variable
D: the second local variable...
The syntax of the function header is then:
function-header ::= result-spec function-and-args local-variables
result-spec ::= empty | Z ←
function-and-args ::= function-spec | function-spec B | A function-spec B
function-spec ::= function | ( LO function ) | ( LO function RO )
function ::= F | F [ X ]
local-variables ::= empty | ; C local-variables
Additional requirements are that all names in the header must be different and
that no name (with the exception of names for local variable names) can be a
user defined name. The name of a local variable may be the name of system
variables, but must not be the name of a system function or primitive.
The possible combinations in the syntax above produces 2×3×3×2 = 36
different header variants. Of these 36 variants the following 7 combinations
are not allowed:
niladic function with axis
monadic operator operator with no value arguments
monadic operator operator with axis and no value arguments
dyadic operator operator with no value arguments
dyadic operator operator with axis and no value arguments
dyadic operator operator with axis and one value argument
dyadic operator operator with axis and two value arguments
The following sections describe the different fields of the function header.
Before that we briefly describe one way to create and display user defined
functions.
3.8.1.1 Creating and displaying defined functions: ⎕FX and ⎕CR
The monadic system function ⎕FX creates a new function. The single argument
of ⎕FX is either a character matrix (the first row of that matrix is the
function header) or a vector of nested character vectors (with the first
character vector the header of the function). The remaining rows of
the matrix or the remaining character vectors are the body lines of the
function being created. On success ⎕FX returns the name of the function
that it has created.
Monadic ⎕CR displays the header and body lines of a function. The single
argument of ⎕CR is the name of the function to be displayed. ⎕CR returns
a matrix with the function header and the function body.
)CLEAR
CLEAR WS
∇FOO
1 + 2
∇
⎕CR 'FOO'
FOO
1 + 2
3.8.1.2 Result Specification
The example above has created a function FOO that had no result specification.
Such functions can be executed, but they do not return a result and attempts
to use their return fails:
)CLEAR
CLEAR WS
∇FOO
1 + 2
∇
FOO ⍝ call FOO (that is OK)
3
VAR←FOO ⍝ try to use FOO's result (that is an error)
3
VALUE ERROR+
VAR←FOO
^
The reason why some value (3) was displayed is not because FOO has returned
the result 3, but because the statement '1 + 2' was not assigned to a variable
and therefore printed.
For a function to return a result, two conditions must be met:
the header must contain a result specification such as Z←, and
the variable named in the result specification must be assigned during
the execution of the function
The result specification is a user-defined name followed by the assignment
arrow ← :
)CLEAR
CLEAR WS
⍝ define FOO returning result Z
∇Z←FOO
Z←1 + 2
∇
FOO ⍝ call FOO
3
VAR←FOO ⍝ try to use FOO's result
VAR ⍝ show result
3
The output of simply calling FOO is the same as before. However, the value
3 is now the result of FOO and not the result of the statement Z←1 + 2 inside
FOO. This is because the assignment Z←1 + 2 is now a committed value which
is not printed.
If the function header has a result specification, but the result variable is
not assigned, then
)CLEAR
CLEAR WS
⍝ define FOO returning Z without assigning Z (which is more often than not an error)
∇Z←FOO
1 + 2
∇
FOO ⍝ call FOO
3
VAR←FOO ⍝ call FOO (OK) and try to use FOO's result (ERROR)
3
VALUE ERROR+
VAR←FOO
^
Forgetting, as above, to assign the result value inside a defined function
whose header indicates that the function returns a result is an error that
is sometimes hard to discover, in particular when the function contains
branches (so that some execution paths assign the result and some don't).
In that case the programmer may be mislead by the fact that the function
header indicates a result and incorrectly assumes that the result variable
is actually assigned before the function returns.
3.8.1.3 Local Variables
The function header can optionally contain a list of local variables. Every
local variable is appended to the function header with a semicolon in front
of it. For example:
A FOO B;C;D
is the header of a dyadic function (with arguments A and B) and local
variables C and D.
At this point we should reveal that every user defined name, and also the
APL system variables have an associated stack, The stack is created when
the name is first mentioned (or from the outset if the name refers to an
APL system variable).
When a user defined function is called, then the stack of the following
names is pushed:
the function result
the function arguments
the local variables, and
labels (see below)
After pushing a name, the name refers to nothing, which is usually changed
shortly after pushing it. The previous values of the name are now
inaccessible. Only the item on the top of a name's stack can be accessed.
The name on the top of the stack remains accessible until either another
(or the same) function with the same name in its local variables is called,
or else until the functions returns. If the function returns then the stacks
of all its local variable names are popped and the previous top of the stack
becomes accessible again.
3.8.1.4 The Del Editor
⎕FX is not the only way to create user defined functions. ⎕FX is good if
the function created is small and is often the only way to create new
functions programmatically. An alternative present in many APL interpreters
is the interactive 'Del' editor. The Del editor is started by entering
the APL character Nabla (∇) and the full header of the new function.
The Del editor has simple commands for displaying, inserting, editing, and
deleting function lines.
The Del editor has a prompt which is the next line to be added or changed;
This line is displayed in square bracket. If the user wants to change a
different line than the line proposed by the Del editor then the desired
line is entered (again in square brackets). The following is an overview of
Del editor commands:
Command
Effect
[N]
Continue editing with line N
[⎕]
display all function lines
[⎕N]
display the function lines 1 to N (inclusive)
[N⎕]
display the function line N and those following
[N⎕M]
display function lines N to M (inclusive)
[∆N]
delete function lines N
[N∆M]
delete function lines N to M
[→]
discard changes
∇
close the Del editor
Entering a non-existing fractional number, like in [3.5] creates a new line
between the closest existing lines (between lines 3 and 4 if there are no
other fractional line numbers between 3 and 4). When the Del editor is
closed then all lines will be renumbered, starting with header line 0.
These days you will probably use your own editor like Vim or emacs
to edit APL functions and then cut-and-paste them into the window in which APL
runs, or start APL with a text file containing function definitions. However,
at the time when the Del editor was developed, computer mice were not yet
invented and terminals were too limited in functionality to support
cut-and-paste. Most commands of the Del editor are irrelevant today, but the
Del editor is still the method of choice when defining functions in
(non-interactive) APL scripts to create new APL functions.
For example, say you have a normal (UTF8 encoded) text file containing
the following:
∇ Z←FOO
1 + 2
∇
That defines the same function as;
⎕FX 'Z←FOO' '1 + 2'
but is more readable, in particular when functions become longer. We will
use this format for displaying functions. The above format is also suitable
for displaying APL code snippets in emails or on web pages. The reader can
simply cut-and-paste them into his interpreter (provided of course, that
the interpreter uses UTF8 encoded Unicode and not special APL fonts).
3.8.1.5 Function Body
The remaining lines of a function are called the function body.
The function body consists of 0 or more function lines. Every
function line consists of 0 or more APL statements like those already
discussed above.
A function line can have an optional label. A label is another kind
of local variable that is automatically created, cannot be changed, and
has an integer value that is equal to the number of the line on which it
was written. For example:
∇A FOO1 B;C;D
L1: 'line 1'
L2: 'line 2'
X←L2
∇
The hypothetical function FOO1 above has two arguments A and B, explicit
local variables C and D, and labels L1 and L2. The syntax for a label is a
name followed by a colon. The variable X would get the value 2 because
label L2 is on line 2. labels are read-only; attempting to change their
value yields a SYNTAX ERROR. Labels will be discussed together with branching
in functions below.
3.8.2 How Functions and Operators are Evaluated
The execution (or evaluation) of a function starts when the function name
is detected in a statement and all its arguments (as defined by the header
of the function) are present. Lets assume we define FOO like this:
)CLEAR
CLEAR WS
⍝ define dyadic FOO with result Z and arguments A and B
Then we enter the following in immediate execution mode:
(3 + 4) FOO 5
line 1
line 2
42
The APL interpreter will see FOO, but it will notice that the left argument
of FOO, i.e. (3 + 4,) is not yet available because the result of (3 + 4) has
not yet been computed. The interpreter will therefore compute (3 + 4) first
and replace it by 7. We have now:
7 FOO 5
The interpreter can now evaluate 7 FOO 5 (or some other function in the
general case) as follows:
first the stacks of all names are pushed. In our example, the names
being pushed are Z, A, B, C, D, L1, and L2 (but not FOO!)
next the actual arguments of the function (7 and 5) are assigned to
the formal parameters (A and B) of the function. That is, A←7 and B←5.
the labels are assigned, i.e. L1←1 and L2←2.
(at this point, the function result Z and the local variables C and D
are undefined, while the function arguments A and B and the labels
have values)
the statements in the function body are executed, starting with the
first statement in the first line.
the function result Z, which may or may not be defined is stored in
a temporary location.
all stacks of all names that were pushed above are popped. They now have
the value they had when FOO was called.
the function and its arguments are replaced by the function result in
the temporary location.
In our example, the following output is produced:
(3 + 4) FOO 5
line 1
line 2
42
The first two output lines ("line 1" and "line 2") are output from lines
1 and 2 of FOO, while the last line is the return value from FOO which
is displayed after FOO has returned.
3.8.3 Branching
The examples of user defined functions given so far were "linear" by which
we mean that the statements in the body of the function were executed one
after the other until the end of the function was reached.
In addition to that, APL provides a means to change the order of the
normal program flow from the beginning of a function to its end: a
computed branch.
APL has been criticized for having only one way of changing the order of
the program flow instead of many (like if/else, for, while, and case in C/C++).
However the computed branch in APL is so powerful that it can easily emulate
the multiple flow control statements in other languages. And the fact that APL
works on larger data structures than scalars makes the low-level loops found
in other languages obsolete.
A computed branch is a statement that consists of a branch arrow (→) and
a numeric APL value. A slightly different statement, called Escape
consists of the same branch arrow, but without the value. For example:
→L ⍝ computed branch (to label L)
→ ⍝ escape
3.8.3.1 Labels
The numeric argument of a computed branch is a line number. So →1 is a
branch to line 1 of some user defined function. However, absolute line
numbers should never be used for branching. The reason is that APL renumbers
the lines of a user defined function when new lines are added between
existing lines. The line numbers in branches are not renumbered when
renumbering lines and as a consequence the absolute line numbers in branches
become invalid. This problem can easily be solved by using labels.
A label is an APL name followed by : (colon) at the beginning of a line.
The label is an automatically created local variable whose value is
the line number on which it was written and the variable is read-only
(i.e. one cannot assign a new value to it). Unlike absolute line numbers,
labels move with their line when other lines are inserted before them and
a subsequent renumbering of lines does them no harm.
Example:
∇FOO
'line 1' ◊ →3 ⍝ Bad: absolute branch to line 3
'line 2' ◊ →L3 ⍝ Good: branch to line 3 with label L3
L3: 'line 3' ◊
∇
If another line is inserted before the first line, then FOO becomes:
∇FOO
'new line before line 1'
'line 1' ◊ →3 ⍝ Bad: absolute branch to line 3
'line 2' ◊ →L3 ⍝ Good: branch to line 3 with label L3
L3: 'line 3' ◊
∇
The previous line 3 with label L3 is now line 4. The branch to the absolute
line number 3, i.e. →3, now branches to the line before the line with label
L3 (which is now most likely wrong), while the branch to label L3 remains
correct.
3.8.3.2 Computed Branch (inside a function)
Inside a function a computed branch →EXPR where EXPR is some APL expression
is executed as follows.
first the expression EXPR is evaluated. If the evaluation of EXPR fails
then this is an error and execution of the function stops as described
later on.
Let X be the result of evaluating EXPR. Then:
if X is empty, then execution continues with the next statement after
the branch. This can be used to emulate an if statement in C++
if X is not empty, then it is expected to be a vector whose first
element is an integer L.
if L is a valid line number, (a number between 1 and
the number of lines in the function (inclusive)) then
then a branch to that line is performed. That is, execution
continues at the first statement on the new line.
Otherwise, i.e. L is ≤ 0 or larger than the number of lines
in the function, then execution of the function is ended.
In the following we explain some examples of frequently used branch patterns
and their "equivalents" in C/C++
⍝ meaning C/C++
→0 ⍝ leave the function return;
→(COND)⍴0 ⍝ dito if COND if (COND) return;
→(COND)↓0 ⍝ dito if not COND if (!COND) return;
→LAB ⍝ goto line LAB goto LAB;
→(COND)⍴LAB ⍝ dito if COND if (COND) goto LAB;
→(COND)↓LAB ⍝ dito if not COND if (!COND) goto LAB;
→⎕LC ⍝ repeat current line
→(COND)⍴⎕LC ⍝ dito if COND do { current line } while (COND)
→⎕LC+1 ⍝ goto next line
→(COND)⍴⎕LC+1 ⍝ dito if COND if (COND) { rest-of-line }
→⎕LC-1 ⍝ goto previous line
→(COND)⍴⎕LC-1 ⍝ dito if COND
→(X=V1,V2 ...)/L1, L2, ...) ⍝ switch(X) { case V1: goto L1; ... }
In the examples above COND is usually a Boolean expression such as A ≤ B.
Since all APL comparison operators have negated forms (=/≠, ≤/>, </≥,
etc.) the (COND)↓ patterns above are far less frequent then the (COND)⍴
patterns. Note also that the (COND)↓ only works for single line numbers
(like 0 or LAB above) but NOT for possibly longer vectors like ⎕LC.
The (COND)⍴ pattern also works for non-Boolean integer expressions (like
if (COND) with non-integer COND in C/C++). It should not be used,
however, if the integer COND is large because then the computation of
⍴ takes a long time and all but the first element of its result is discarded.
To avoid that, use 0≠COND instead of COND if COND may be a large integer.
3.8.3.3 Computed Branch (outside a function)
If a computed branch statement is executed outside a function (for example
after an error in a function interrupts the execution of the function and
returns to immediate execution mode) then the branch is executed as if it
were executed inside the interrupted function. An error is thrown if no
interrupted function exists.
This can be used to jump back (i.e. continue) the execution of a function
that was interrupted (typically after removing the cause of the error).
3.8.3.4 Escape (Unwind)
A single → terminates the execution of the current defined function and
removes it from the )SI stack. After that the caller of the current defined
function becomes the current defined function.
4 Commands
Every APL interpreter provides a number of commands that can be entered in
immediate execution mode. The ISO standard defines a small number of standard
commands, and every interpreter adds its own commands for various purposes.
Commands do not follow the syntax of the APL language, but are more similar to
the input of a shell (a command, followed by mandatory or optional arguments).
A command starts with the character ) (or ] for some interpreters) followed by
a name.
4.1 Standard Commands
4.1.1 )CLEAR
Syntax: )CLEAR
Re-initializes the current workspace. All user-defined functions and
variables are deleted and all system variables are reset to their default
values. The workspace name is set to CLEAR WS.
4.1.2 )COPY
Syntax: )COPY [lib] wsname [object ...]
lib is an optional library reference number from 0 to 9. If lib
is omitted then it is taken to be 0. The library reference number selects
one of 10 directories (which can be configured elsewhere, see command
)LIBS below) that contain workspace files.
wsname then selects a workspace file in the directory selected by lib.
Normally the name of the workspace file is either wsname.apl or else
wsname.xml. However, if lib is omitted, then the workspace file
need not be contained in the directory corresponding to library reference 0,
but wsname may instead be an absolute path to the workspace file that
shall be copied. This can be useful if the workspace file resides in a
non-standard (according to )LIBS) directory, or if both wsname.apl
and wsname.xml exist in the same directory.
If object(s) is omitted, then all user-defined variables,
defined functions, and defined operators in the selected workspace
are copied into the current workspace.
Otherwise only those user-defined variables, defined functions, and defined
operators whose names starts with one of the names in object ... are
copied into the current workspace.
4.1.3 )COPY_ONCE
Like )COPY, but the workspace file is copied at most once. Subsequent
)COPY_ONCE of the same workspace file will be ignored.
4.1.4 )DROP
Syntax: )DROP [lib] wsname
lib is an optional library reference number as for command )COPY
above.
wsname selects a workspace in the directory selected by lib. If
lib is omitted then an absolute path to the workspace file is accepted
as wsname.
Delete the workspace (CAUTION: without any warning).
4.1.5 )ERASE
Syntax: )ERASE symbol ...
The variable, defined function, or defined operator with name symbol
is deleted in the current workspace.
4.1.6 )FNS
Syntax: )FNS [from-to]
Display the names of defined functions in the current workspace.
For workspaces with many defined functions, characters from and to
can be used as a filter that specifies an alphabetic range of names.
4.1.7 )LIB
Syntax: )LIB [lib|path] [from-to] [sort]
lib is an optional library reference number as for command )COPY
above. Alternatively, path may be the absolute path to a non-standard
directory that contains workspace files.
from-to is an optional name filter like in )FNS above.
sort is an optional sorting mode, either -size or else -time.
The workspaces in the selected directory are displayed.
For directories with many workspace files, characters from and
to can be used as a filter that specifies an alphabetic range of names.
If no sorting mode is specified then )LIB shows workspaces names
(see )WSID below), i.e. without their ,apl or .xml
file name extension. Otherwise the file names are displayed with
their .apl or .xml extension.
4.1.8 )LOAD
Syntax: )LOAD [lib] wsname
lib is an optional library reference number as for command )COPY
above.
wsname selects a workspace in the directory selected by lib. If
lib is omitted then an absolute path to the workspace file is accepted
as wsname. The current )WSID is updated accordingly.
The current workspace is discarded and the workspace stored in the
selected workspace file is made the current workspace.
4.1.9 )NMS
Syntax: )NMS [from-to]
Display the names of variables, defined functions, and defined operators
in the current workspace.
For workspaces with many names, characters from and to can be
used as a filter that specifies an alphabetic range of names.
4.1.10 )OPS
Syntax: )OPS [from-to]
Display the names of defined operators in the current workspace.
For workspaces with many defined operators, characters from and to
can be used as a filter that specifies an alphabetic range of names.
4.1.11 )SAVE
Syntax: )SAVE
Save the current workspace in the file wsname.xml where wsname
is defined by the current workspace name (as per )WSID).
Syntax: )SAVE [lib] wsname
lib is an optional library reference number as for command )COPY
above.
wsname selects a workspace in the directory selected by lib. If
lib is omitted then an absolute path to the workspace file is accepted
as wsname and this becomes the new workspace id.
Save the current workspace in the file wsname.xml in the directory
selected by lib.
4.1.12 )SI
Syntax: )SI
Every workspace contains a so-called State Indicator similar to the
stack-trace of a C program when run in a debugger. Every time a defined
function is called a new entry for the defined function is added, and
the entry is deleted again when the defined function returns. Due to this
last-in-first-out nature the State Indicator is also called the
)SI stack.
When the interpreter returns to immediate execution as a result of an
error, then the command )SI can be used to display the (recursive)
set of defined functions that have been called but not yet finished, and
the line number of the current statement in each function.
The )SI command itself displays only the function name and its line
number. However there exist several variants of the )SI command that
provide additional information for debugging purposes. For example:
⍝ clear the SI stack
)SIC
⍝ show the SI stack (which is always empty after )SIC)
)SI
∇FOO;A;B;C
1 + 2
÷0 ⍝ provoke a DOMAIN ERROR'
∇
FOO
3
DOMAIN ERROR
FOO[2] ÷0
^
⍝ show the SI stack again
)SI
FOO[2]
⋆
In the output of command )SI: an immediate execution entry is displayed
as * while a defined function is displayed as the function name followed
by a line number of the function in brackets. In the example above:
The first line is the )SI entry for the execution of FOO. The
execution was stopped in line 2 due to the DOMAIN ERROR, and
The last * is the )SI entry for the immediate execution context in which
command )SI was entered. Whenever APL detects an error, it stops execution and
created a new )SI entry with mode immediate execution in which the user can
then issue commands like )SI and/or change variables, and/or continue execution
at the point where the error was detected.
4.1.13 )SIC
Syntax: )SIC
Clear the )SI stack (remove all items and release its resources,
particularly localized variables).
4.1.14 )SINL
Syntax: )SINL
)SI with Name List. Same as )SI, but the display of the )SI stack is augmented
with the local variables of the function called. In the )SI example:
)SINL
FOO[2] A B C
⋆
The first line shows that function FOO was called and has localized the names
A, B, and C. The second line is an immediate execution context (which cannot
localize variables). )SINL is useful for determining the scope of a variable
(e.g. which defined function has last localized it).
4.1.15 )SIS
Syntax: )SIS
)SI with Statement. Same as )SI, but the display of the )SI stack is augmented
with the current statement in the function called (and possibly the error
message if the statement had raised an error). In the )SI example:
)SIS
FOO[2] ÷0
^
⋆ FOO
^
The first line shows the APL statement ÷0 in line 2 of FOO which caused
the DOMAIN ERROR. The second line shows the statemant FOO that called
FOO. The order in the display of the )SI stack is therefore from most recent
to least recent (or downwards from called function to calling function).
4.1.16 )VARS
Syntax: )VARS [from-to]
Display the names of user-defined variables in the current workspace.
For workspaces with many user-defined variables, characters from and
to can be used as a filter that specifies an alphabetic range of names.
4.1.17 )WSID
Syntax: )WSID
Display the name of the current workspace.
Syntax: )WSID wsname
Set the name of the current workspace to wsname. The name of the
workspace is used, for example, when )DUMP or )SAVE is used and the
filename is ommitted.
4.2 IBM APL2 Commands
GNU APL also understands most of the IBM APL2 commands.
4.2.1 )CHECK
Syntax: )CHECK
Perform an internal check of the internal data structures, primarily to
detect memory leaks.
4.2.2 )CONTINUE
Syntax: )CONTINUE
Save the current workspace under the name CONTINUE.xml and exit. If APL is
started later on and a workspace named CONTINUE exists, then that workspaces
is )LOADed automatically. In other words, the APL session is continued
at the point where it was left with command )CONTINUE.
4.2.3 )HELP
Syntax: )HELP
Display a list of all GNU APL commands, system variables, and system functions.
Syntax: )HELP primitive
Display a brief help text for the APL primitive primitive.
4.2.4 )HOST
Syntax: )HOST command ...
Execute command command ... in the operating system under which GNU APL
runs.
4.2.5 )IN
Syntax: )IN filename [object ...]
Like )LOAD filename [object ...], but for a workspace saved with
command )OUT (see below).
4.2.6 )MORE
Syntax: )MORE
APL errors like DOMAIN ERROR, INDEX ERROR etc. are displayed
automatically if they occur. For some of these errors, the interpreter has
additional information which is, however, not displayed automatically.
Command )MORE may display this additional information. Example:
1 2 3 ⎕MAP 1 2 3
LENGTH ERROR+
1 2 3 ⎕MAP 1 2 3
^ ^
)MORE
Odd length of A in A ⎕MAP B
A + character at the end of the APL error indicates that some additional
information is present and can be displayed with )MORE but it
must be invoked before anything else is done.
4.2.7 )OUT
Syntax: )OUT filename [object ...]
Like )SAVE below, but using a different file format. The files have an
extension of .atf (for APL Transfer File). Even though the )SAVE
command itself is standardized (in the ISO standard), the file format that
it produces is not. In contrast, the file format produced by )OUT and
understood by )IN is supposed to be understood by different APL
interpreters of different vendors, so that workspaces can, at least in
principle, be exchanged using )IN and )OUT.
Some vendors have extended the .atf file format, which undermines its
primary purpose. GNU APL only supports the original format as described in
the IBM APL2 Language Reference Manual.
4.2.8 )OFF
Syntax: )OFF
Exit the APL interpreter with exit code 0.
Syntax: )OFF [exit_code]
Exit the APL interpreter with the given exit code.
4.2.9 )PCOPY
Syntax: )PCOPY [lib] wsname [object ...]
Protective )COPY. Same as )COPY above, but not overwriting existing
defined functions and variables.
4.2.10 )PIN
Syntax: )PIN filename [object ...]
Protective )IN. Same as )IN above, but not overwriting existing
defined functions and variables.
4.2.11 )RESET
Syntax: )RESET
Same as )CLEAR above.
4.2.12 )SYMBOLS
Syntax: )SYMBOLS [count]
If count is ommitted then display the current number of user-defined
names (i.e. for variables, labels, defined functions and defined operators).
Otherwise, increase the size of the symbol table to at least count.
4.3 Additional GNU APL Commands
In addition to the commands from the ISO standard and from IBM APL2, GNU APL
provides some more commands. These commands are divided into 2 groups: normal
commands that start with the character ), and debug commands that
start with the character ].
4.3.1 )DUMP
Syntax: )DUMP [[lib] wsname]
Like )SAVE below, but using a different file format. The files have an
extension of .apl. The file produced is an APL script which, when executed,
reconstructs the current workspace (in terms of variables, defined functions,
and defined operators).
The .apl files produced by )DUMP are easier to read (and, if necessary,
to modify) than the .xml files produced by )SAVE. On the one hand, .apl
files are more portable than .xml files, both in respect to different versions
of the GNU APL interpreter and with respect to interpreters from different APL
vendors. On the other hand, .apl files have limitations when used with
)COPY in libapl.
4.3.2 )DUMP-HTML
Syntax: )DUMP-HTML [[lib] wsname]
lib is an optional library reference number as for command )COPY
above.
wsname selects a workspace in the directory selected by lib. If
lib is omitted then an absolute path to the workspace file is accepted
as wsname.
)DUMP-HTML is similar to )DUMP, but it adds some HTML tagging so that the
output file (with file extension .html) can be directly displayed by a web
server. This can be useful for sharing your workspaces on the web in such
a way that other users can cut-and-paste your code into their GNU APL session.
4.3.3 )HIST
Syntax: )HIST ⍝ show entire history
Syntax: )HIST CLEAR ⍝ clear the history
Syntax: )HIST filter ⍝ show only history lines starting with filter
)HIST displays previously entered lines. It is sometimes difficult to remember
the APL input that has lead to an APL error, and this command may help to
reproduce such errors.
If called with an argument, then argument CLEAR clears the history, while
any other argument is taken as display filter. Only history lines beginning
with the given filter are being displayed.
4.3.4 )LIBS
Syntax: )LIBS
Display the current mapping from library reference numbers to directories. For
example:
)LIBS
Library root: /home/eedjsa/apl-1.9
Library reference number to (absolute) path mapping:
╔═══╤═════╤═════════════╤══════════════════════════════════════════════════════╗
║Ref│Conf │State (errno)│ Path to the directory containing the workspace files ║
╟───┼─────┼─────────────┼──────────────────────────────────────────────────────╢
║ 0 │PWD │ present │ /home/eedjsa/apl-1.9/workspaces ║
║ 1 │PWD │ present │ /home/eedjsa/apl-1.9/wslib1 ║
║ 2 │PWD │ present │ /home/eedjsa/apl-1.9/wslib2 ║
║ 3 │PSYS │ present │ /usr/local/lib/apl/wslib3 ║
║ 4 │PSYS │ present │ /usr/local/lib/apl/wslib4 ║
║ 5 │PSYS │ present │ /usr/local/lib/apl/wslib5 ║
║ 6 │PWD │ present │ /home/eedjsa/apl-1.9/wslib6 ║
║ 7 │PWD │ missing (2) │ /home/eedjsa/apl-1.9/wslib7 ║
║ 8 │PWD │ missing (2) │ /home/eedjsa/apl-1.9/wslib8 ║
║ 9 │PWD │ missing (2) │ /home/eedjsa/apl-1.9/wslib9 ║
╚═══╧══╤══╧═════════════╧══════════════════════════════════════════════════════╝
│
├── NONE: found no method to compute the library path
├── CMD: the path was set with )LIBS N path
├── ENV: the path came from environment variable $APL_LIB_ROOT
├── PSYS: the path came from the system preferences in file
│ /usr/local/etc/gnu-apl.d/preferences
├── PUSER: the path came from user preferences in file
│ $HOME/.config/gnu-apl or $HOME/.gnu-apl
└── PWD: the path is relative to current directory $PWD (last resort)
Syntax: )LIBS [lib] path
lib is an optional library reference number as for command )COPY
above.
The directory for library reference number lib is set to path.
4.3.5 )QLOAD
Syntax: )QLOAD [lib] wsname
Quiet )LOAD. Like )LOAD) above, but without printing a SAVED...
or DUMPED ... message.
4.3.6 )VALUES
Syntax: )VALUES
Display a (long) list of all APL values (not variables) currently known
by the interpreter along with their status (for debug purposes).
4.3.7 ]BOXING
Syntax: ]BOXING [OFF|2|3|4|7|8|9]
Changes the default style of the APL output. Example:
Enables or disables the emission of Escape sequences for colors in the APL
output. Output coloring is typically useful in truly interactive mode but
requires terminals or terminal windows that support the Escape sequences.
There are many situations, however, in which these Escape sequences disturb
more than they help, e.g. copy-and-paste between terminal windows,
post-processing of APL output.
4.3.9 ]DOXY
Syntax: ]DOXY [path]
Produce a Doxgen-like documentation of the current workspace. If path
is omitted then current directory is used as path. Example:
⍝ ]DOXY refuses to overwrite existing directories.
)HOST rm -Rf /tmp/DOXY_TEST
0
)WSID DOXY_TEST
WAS CLEAR WS
]DOXY /tmp
Command ]DOXY finished successfully.
The generated documentation was stored in directory /tmp/DOXY_TEST
You may now browse it from file:///tmp/DOXY_TEST/index.html
4.3.10 ]EXPECT
Syntax: ]EXPECT error_count
Accept up to error_count errors before a testcase is considered failed.
4.3.11 ]KEYB
Syntax: ]KEYB
Display an APL Keyboard that can, for example, be used for cut-and-paste of
APL characters on keyboards that cannot produce them. For example:
The user may change the keyboard that is displayed with ]KEYB, see e.g.
/usr/local/etc/gnu-apl.d/keyboard1.txt.
4.3.12 ]LOG
Syntax: ]LOG [facility [ON|OFF]]
Lists or controls GNU APL logging facilities (if configured to do so).
4.3.13 ]NEXTFILE
Syntax: ]NEXTFILE
GNU APL can be started with no, one, or muktiple input files. The
]NEXTFILE command abortes the execution of the current input file and
starts the execution of the next file (if any). If there is no next file
then it prints an error message and enters immediate execution mode.
4.3.14 ]OWNERS
Syntax: ]OWNERS
Displays some debug information related to all APL values.
4.3.15 ]SVARS
Syntax: ]SVARS
Displays some debug information related to shared variables
(an obsolete APL feature that is still supported by GNU APL).
4.3.16 ]SYMBOL
Syntax: ]SYMBOL name
Displays some debug information related to name.
4.3.17 ]USERCMD
GNU APL allows the creation of new APL commands by the user. These commands are
implemented as APL code, either as lambdas (for simple commands) or as defined
functions (for more complex commands).
Syntax: ]USERCMD
Display all currently defined user commands.
Syntax: ]USERCMD )ucmd APL_fun [mode]
Syntax: ]USERCMD ]ucmd APL_fun [mode]
Define a new user-defined command by means of a defined function. The entire
command is passed to the defined function as a string, therefore the function
usually needs to drop the name of the command.
If the optional mode is 0 (which is the default) then APL_fun
shall be monadic and the command entered by the user is passed to APL_fun
as an APL string (starting with the command name). APL_fun is responsible
for parsing the string, typically at least dropping the name of the command.
If the optional mode is 1 then APL_fun shall be dyadic. The right
argument of APL_fun is the same as for mode 0, while the left argument
is a nested vector of APL strings. This vector contains the tokenized right
argument which somewhat simplifies the processing of the argument(s) with which
the user-defined command was called. The first item of the vector is the
command, the next item is the first argument (if provided), and so on.
It is possible to use the same defined function for different user-defined
commands.
Define a new user defined command by means of a monadic lambda expression.
The entire command is passed to the lambda expression as a string, therefore
the lambda expression needs to drop e.g. the name of the command. Example:
First define the command:
]USERCMD )sum { +/⍎4↓⍵ }
User-defined command )sum installed.
Then use the new command:
)sum 1 2 3
6
Syntax: ]USERCMD REMOVE ]ucmd
Delete the previously defined user command ]ucmd. Example:
]USERCMD REMOVE )sum
User-defined command )sum removed.
Syntax: ]USERCMD REMOVE-ALL
Delete all currently defined user commands.
]USERCMD REMOVE-ALL
All user-defined commands removed.
4.3.18 ]XTERM
Syntax: ]XTERM [ON|OFF]
GNU APL assumes, by default, that it runs interactively in an xterm compatible
terminal or terminal emulator such as xterm. In some situations it needs
to output Escape sequences, e.g. for positioning the cursor or for clearing
lines. In some situations (see command ]COLOR) these Escape sequences
are not desired and their emission can be turned off with command XTERM