One of the first programming languages I learned in university was APL (“A Programming Language”). I wouldn’t call it my favorite language, but it’s certainly a lot of fun.
Lines of code are read right to left; the syntax involves around a hundred non-alphanumeric symbols (and a unique keyboard); and its central datatype is a multidimensional array (of which scalars and vectors are special cases).
The syntax is very concise, allowing the programmer to represent a complex algorithm with a small number of characters, sometimes with a single line of code. Here are some examples:
Example 1
Consider this code:
×/⍳6
It calculates and returns 6! (“6 factorial”), which is the product of the first six positive integers:
720
To understand the code, start at the right end of the line. This code
⍳6
generates a 6-element vector comprised of the integers from 1 to 6:
1 2 3 4 5 6
Reading now to the left, this code
×/⍳6
generates a scalar value by multiplying together all of the elements in our vector:
720
Example 2
More simply in Example 1, we could have used APL’s built-in factorial operator to arrive at the same result:
!6
720
Factorial is an example of a monadic operator, because it operates on only a single operand, in this case the scalar value 6.
We should read our code from right to left: We begin with 6 and then, reading to the left, we apply the factorial operator. So we write !6
instead of 6!
.
By the way, the plus operator is said to be dyadic rather than monadic, because it operates on two operands:
3 + 4
7
Example 3
Consider this code:
+/4=?10000⍴6
It returns the number of 4s that come up after 10,000 random throws of a 6-sided die. For example, I just got this result:
1683
To understand the code, start as always at the right end of the line. This code
10000⍴6
returns a vector comprised of 10,000 elements of the scalar value 6:
6 6 6 6 6 6 6 6 6 6 ...
Continuing to read the line from right the left, this code
?10000⍴6
applies the monadic randomize operator to each of those 10,000 elements, so each value is now a random integer from 1 to 6:
3 4 2 2 1 3 6 4 3 2 ...
Continuing to read the line to the left, this code
4=?10000⍴6
applies the dyadic equal operator to compare the scalar value 4 with each of the 10,000 elements in our vector, returning for each element either a 1 (equal) or 0 (not equal):
0 1 0 0 0 0 0 1 0 0 ...
Finally, we arrive at the left end of the line, where this code
+/4=?10000⍴6
sums the 10,000 1s and 0s in our vector, returning a scalar value which is the count of 4s we rolled altogether:
1683
Example 4
Consider this code:
+/(⍳6)∘.=?10000⍴6
It returns a vector with the count of 1s, 2s, 3s, 4s, 5s and 6s achieved, respectively, after 10,000 random throws of a 6-sided die. For example, I just got this result:
1732 1673 1689 1574 1644 1688
To understand the code, start again at the right end of the line. We have already seen in Example 3 that this code
?10000⍴6
generates a vector with 10,000 random integers from 1 to 6:
3 5 1 4 1 2 5 4 1 4 ...
Still reading to the left, we see a dyadic operation between two vector operands.
(⍳6)∘.=?10000⍴6
The operand on the right is our vector of 10,000 random integers, while the operand on the left is a 6-element vector comprised of the integers 1 to 6, as we saw in Example 1:
⍳6
1 2 3 4 5 6
The result of the dyadic operation is a 2-dimensional matrix which represents the outer product of the vectors when the equals operator is applied to pairs of values from the two vectors:
0 0 0 0 0 0 0 0 0 0 ...
0 0 0 1 0 0 0 0 0 0 ...
0 0 0 0 0 0 1 0 0 0 ...
0 1 1 0 0 1 0 1 1 1 ...
1 0 0 0 0 0 0 0 0 0 ...
0 0 0 0 1 0 0 0 0 0 ...
So, for example, the fourth row contains 10,000 values of 1 or 0, depending on whether the corresponding value in our array of random integers is equal to 4.
Finally, we arrive at the left end of the line, where this code
+/(⍳6)∘.=?10000⍴6
returns a vector of six elements, each the sum of values in a different row of the matrix:
1732 1673 1689 1574 1644 1688
Example 5
As a sanity check, we can sum the elements of the vector result of Example 4:
+/+/(⍳6)∘.=?10000⍴6
10000
If our code in Example 4 is right, the result here should always be 10,000.
My first paying job, while I was a university student, that applied what I had learned in university involved APL programming on the IBM 5110 desktop computer (a precursor to the IBM PC):
Notice the special APL symbols on the keyboard keys.
You can try for yourself, interactively, some APL programming here: