APL - Language features
After the introduction to APL in the last post, let’s now look in more detail on how APL works.
As the emulated system does not support entry and display of APL symbols, we will have to use transliterations, eg * for the multiply symbol ×. The code samples below show the original version on the left and the transliterated version on the right. An appendix at the end of this post lists all symbols used and their transliterations.
The interpreter
Similar to the last language we looked at, PIL, when APL starts up it allows you to enter expressions and get results immediately. The prompt is eight leading spaces and results are printed in the first column.
21 × 2 21 * 2
42 42
a "string"
Monadic and dyadic functions
We can enter simple arithmetic functions and get results as expected.
21 + 2 21 + 2
23 23
21 − 2 21 - 2
19 19
21 ÷ 2 21 / 2
10.5 10.5
These are all dyadic functions, ie they take a left and right parameter. Many APL functions also have monadic versions which take only one parameter on the right. Let’s look at how the four basic arithmetic functions work:
+21 +21
21 21
−21 -21
−21 _21
×21 *21
1 1
÷21 /21
0.04761904762 0.04761904762
Plus and minus work as expected; note that negative numbers are displayed with a leading underscore to represent the −
symbol. Multiply and divide give more interesting results. Multiply gives the signum of its parameter: -1 if negative, 0 if zero or 1 if positive. Divide gives the reciprocal of its parameter.
The modulus operator (∣
or $|
) works the opposite way around from what you may be used to from other languages, so 10 ∣ 12
is 2
.
Order of execution is strictly right to left; using brackets allows you to specify what operators works on what parameters
2×3+2 2*3+2
10 10
÷2×3+2 /2*3+2
0.1 0.1
(2×3)+2 (2*3)+2
8 8
Variables and types
Values can be assigned to a variable with ←
(=
). Variable names need to start with a letter. Underlined letters can also be used; these are transliterated to lower case letters.
X ← 3 X = 3
Y ← 22 Y = 22
Z ← X × Y Z = X * Y
Z Z
66 66
As well as single numbers, you can have vectors of numbers. These are entered by separating the elements with spaces. Operators work on vectors as well.
X ← 1 2 3 X = 1 2 3
Y ← 10 100 1000 Y = 10 100 1000
X × Y X * Y
10 200 3000 10 200 3000
If the dimension of the parameters differ, APL will extend the shorter vector as appropriate - so 1 2 3 × 2
will give 2 4 6
.
Strings are introduced using quotes; internally APL treats them as vectors of characters.
Booleans are represented as numbers with a value of 0 or 1. These are returned by comparison functions like equal, greater or equal (=
, ≥
or =
, $GE
). Logical operators like and (∧
or &
) can operate on these.
3 ≥ 2 3 $GE 2
1 1
(3 ≥ 2) ∧ (2 = 2) (3 $GE 2) & (2 $EQ 2)
1 1
Vector functions
The rho function (⍴
or $,
) gives the dimension of a vector when used moadically. Used dyadically, it can create a matrix from a vector on its right side by giving the shape on the left side.
⍴ 10 20 30 $, 10 20 30
3 3
X ← 1 2 3 4 5 6 7 8 X = 1 2 3 4 5 6 7 8
9 10 9 10
2 5 ⍴ X 2 5 $, X
1 2 3 4 5 1 2 3 4 5
6 7 8 9 10 6 7 8 9 10
Comma (,
) used dyadically is called catenate, and adds to a vector.
x ← 1 2 3 4 5 x = 1 2 3 4 5
x , 6 x , 6
1 2 3 4 5 6 1 2 3 4 5 6
Monadic comma (known as ravel) turns a scalar into a vector
,1 ,1
1 1
A vector of length 1 looks like a scalar when displayed. We can tell them apart with double rho, which gives the rank.
⍴⍴ 1 $,$, 1
0 0
⍴⍴ ,1 $,$, ,1
1 1
Iota (⍳
, which can be transliterated as any of $IO
, $IN
or $.
) creates a sequence when used monadically and gives index positions when used dyadically. Square brackets can be used to extract elements based on index positions.
⍳ 5 $IO 5
1 2 3 4 5 1 2 3 4 5
X ← 'ABCDEFGHIJ' X = 'ABCDEFGHIJ'
X ⍳ 'CAFE' X $IN 'CAFE'
3 1 6 5 3 1 6 5
X ⍳ 'CAZE' X $IN 'CAZE'
3 1 11 5 3 1 11 5
X[X ⍳ 'CAFE'] X[X $IN 'CAFE']
CAFE CAFE
More APL functions
There are over 50 APL functions so it would be difficult to go through them all here, but let’s take a brief tour to show some of them in action.
Ceiling (⌈
or $CE
, $MA
) and floor (⌊
or $FL
, $MI
) rounds up/down when used monadically and finds the max/min when used dyadically
⌈ 2.3 $CE 2.3
3 3
⌊ 2.3 $FL 2.3
2 2
3 ⌈ 2 3 $CE 2
3 3
Factorial (!
) means take m of n when used dyadically:
!5 !5
120 120
2 ! 4 2 ! 4
6 6
Rotation (⌽
, $RO
):
⌽ 1 2 3 $RO 1 2 3
3 2 1 3 2 1
2 ⌽ 1 2 3 2 $RO 1 2 3
3 1 2 3 1 2
Take (↑
, $TA
) and drop (↓
, $DR
):
3 ↑ ⍳ 10 3 $TA $IO 10
1 2 3 1 2 3
3 ↓ ⍳ 10 3 $DR $IO 10
4 5 6 7 8 9 10 4 5 6 7 8 9 10
Grade up (⍋
or $GU
) gives sorted indices, with grade down doing sort in reversed order.
X ← 2 14 1 42 X = 2 14 1 42
⍋ X $GU X
3 1 2 4 3 1 2 4
X[⍋ X] X[$GU X]
1 2 14 42 1 2 14 42
?
used monadically is known as roll, producing a random number between 1 and the right hand argument. Used dyadically, it is known as deal: x ? y
means take x
unique items at random from the population 1 .. y
.
?6 ?6
3 3
?6 ?6
5 5
3 ? 6 3 ? 6
6 2 3 6 2 3
3 ? 6 3 ? 6
3 4 5 3 4 5
Decode (⊥
or $DE
, $BA
) converts bases. Encode (⊤
or $EN
, $RP
) goes the other way. Below we show 2 hours 30 minutes decoded into number of minutes and then re-encoded.
60 60 ⊥ 2 30 60 60 $DE 2 30
150 150
60 60 ⊤ 150 60 60 $EN 150
2 30 2 30
Operators
An operator in APL differs from a function in that it takes a function on its left hand side. One example is reduction (/
or %
): in the example below we give it the plus function which will sum up the elements on the right
+/ 1 2 3 4 +% 1 2 3 4
10 10
Let’s try it with -
:
-% 1 2 3 4 -% 1 2 3 4
-2 _2
Why does it return -2? This is due to the right to left associativity of APL: we could expand this as 1 - (2 - (3 - 4)).
Defining your own functions
You can define your own functions with del (∇
or "
), Starting a line with del creates a function: the rest of the line specifies the variable that will contain the return value, the function name and its parameters. On subsequent lines, APL will prompt you for the next statement with the line number. A del on its own will close the function. A simple example for a monadic function called INCR
that increments its right hand side:
∇ C ← INCR A " C = INCR A
<1> C ← A + 1 <1> C = A + 1
<2> ∇ <2> "
INCR 3 INCR 3
4 4
Dyadic functions are created by giving variables before and after the function names. For example, the hypotenuse function:
∇ C ← A HYP B " C = A HYP B
<1> C ← ((A⋆2) + (B⋆2)) <1> C = ((A@2) + (B@2))
⋆ 0.5 @ 0.5
<2> ∇ <2> "
3 HYP 4 3 HYP 4
5 5
Apart from the parameters, any variables used in defined functions will be global by default. To set up local variables, add a semicolon and the variable names on the function definition line.
∇ Z ← X FOO Y; A " Z = X FOO Y;
<1> A ← X + Y <1> A = X + Y
<2> Z ← A + 2 <2> Z = A + 2
<3> ∇ <3> "
3 FOO 5 3 FOO 5
10 10
Flow control in a function can be introduced with the branch function (→
or $GO
), which takes the line number to branch to on the right hand side. Branching to line number 0 is equivalent to returning from the function: we saw the in part 1 of this series with the line
→ 2 × N < 5 $GO 2 * N $LE 5
which would branch to line 2 if N
was less than 5, else return from
the function.
After defining a function, you can list its contents by entering del, the function name, quad (⎕
or #
) in square brackets then del, all on the same line.
∇FOO[⎕]∇ "FOO[#]"
You can edit or append lines in a function by replacing quad in the above example with a line number. Line numbers can include decimal points, eg to insert a line between current lines 1 and 2 you’d do ∇FOO[1.5]∇
To delete an entire function you need to use the erase system command with the function name, eg )ERASE FOO
.
System commands and workspaces
System commands, starting with )
, manipulate the APL environment. )OFF
will quit APL, )FNS
and )VARS
will list currently defined functions and variables respectively.
To manage sets of functions and variables, APL has the concept of workspaces. The current set can be saved to a named workspace, eg FOO
by the user with the command )SAVE FOO
and then loaded later with )LOAD FOO
. APL will also automatically save the current set to the workspace CONTINUE
on exit and load it again at startup. To wipe out the current running set, use )CLEAR
; to delete from disk user )DROP ws
.
There are also system workspaces, organised into libraries identified by numbers. Use )LIB n
to see the workspaces in library n
and then )LOAD n ws
to load a names workspace. For example, let’s look at the workspace APLCOURSE
in library 1. This defines a function DESCRIBE
which explains its contents.
)LIB 1
ADVANCEDE
APLCOURSE
CLASS
NEWS
PLOTFORMA
TYPEDRILL
WSFNS
EIGENVALU
BRFNS
)LOAD 1 APLCOURSE
SAVED 16.13.05 08%08%68
)FNS
B1X CHECK DESCRIBE DIM DRILL DYAD1 DYAD2 EASY
EASYDRILL FORM FUNDRILL GET INPUT QUES RANDOM
REDSCAPATCH REPP TEACH
DESCRIBE
THE MAIN FUNCTIONS IN THIS LIBRARY WORKSPACE ARE:
TEACH
EASYDRILL
ALL OTHER FUNCTIONS ARE SUBFUNCTIONS AND ARE NOT
SELF-CONTAINED.
SYNTAX DESCRIPTION
______ ___________
TEACH AN EXERCISE IN APL FUNCTIONS USING SCALARS
AND VECTORS. THE FUNCTION PRINTS OUT THE
CHOICES AND OPTIONS AVAILABLE. EXAMPLES
ARE SELECTED AT RANDOM WITH A RANDOM
STARTING POINT.
EASYDRILL THIS IS THE SAME AS TEACH EXCEPT THAT THE
PROBLEMS SELECTED ARE GENERALLY SIMPLER IN
STRUCTURE. PROBLEMS INVOLVING VECTORS OF
LENGTH ZERO OR ONE ARE EXCLUDED.
Workspace 6 contains a resource management game called KINGDOM.
In the next post we’ll look at implementing a real program in APL.
Further information
This post has only scratched the surface of APL. See the Further Information section in the APL introduction post for more resources to learn about APL.
Appendix: Transliterations
This is a copy of the table UM Computing Center Memo 382, excluding characters that are marked as not in use.
Meaning | APL Symbol | Transliteration |
---|---|---|
And | ∧ | & |
Branch | → | $GO $> |
Ceiling | ⌈ | $CE $MA |
Circular functions | ○ | $$ $CI $PI |
Comma | , | , |
Comment / lamp | ⍝ | $* $CO |
Compression | / | % |
Compression axis 1 | ⌿ | $C1 |
Deal / random | ? | ? |
Decode | ⊥ | $DE $BA |
Del | ∇ | " |
Delta | Δ | $" |
Delta underlined | ⍙ | $U" |
Divide | ÷ | / |
Drop | ↓ | $DR $DO |
Encode | ⊤ | $EN $RP |
Equal | = | $EQ |
Expansion | \ | $% |
Expansion axis 1 | ⍀ | $X1 |
Exponentiation | ⋆ | @ |
Factorial | ! | ! $FA $BC |
Floor | ⌊ | $FL $MI |
Grade down | ⍒ | $GD |
Grade up | ⍋ | $GU |
Greater or equal | ≥ | $GE |
Greater than | > | $GT |
Ibeam | ⌶ | $IB $SY |
Iota | ⍳ | $IO $IN $. |
Less or equal | ≤ | $LE |
Less than | < | $LT |
Locked function | ⍫ | $L" |
Logarithm | ⍟ | $@ $LO $LN |
Membership | ∈ | $EP $ME |
Minus | − | - |
Modulus | ∣ | $MO |
Multiply | × | * |
Nand | ⍲ | $N& |
Negation / overbar | − | _ $- |
Nor | ⍱ | $N $WR |
Not | ~ | $NO |
Not equal | ≠ | $NE |
Null | ∘ | $: |
Or | ∨ | | $OR |
Period | . | . |
Plus | + | + |
Quad | ⎕ | # |
Quad-quote | ⍞ | $# |
Quote | ' | ' |
Random | ? | ? |
Rho / dimension | ⍴ | $, $RH $DI |
Rotation | ⌽ | $RO $RV |
Rotation axis 1 | ⊖ | $R1 |
Semicolon | ; | ; |
Specification | ← | = |
Take | ↑ | $TA $UP |
Transposition | ⍉ | $TR |
Underlined letters | A - Z</u | a - z _A - _Z |