The Programming of Wizards
APL (A Programming Language) is an exceptionally unique language. It mainly follows an array paradigm, unlike the usual functional and object-oriented approaches; it depends heavily on weird mathematical glyphs; and it is surprisingly elegant.
History of Old Wizardy
APL is a quite old language. It started as a book (under the same name) written by Kenneth Eugene Iverson in 1962. The focus of the book was mathematical notation. Ken was dissatisfied with the inconsistency of mathematical notation and the lack of a sufficient tool to describe computer algorithms especially when it comes to matrices. Thus, he created what he later won a Turing Award for.
The notation was used inside IBM (his workplace) for describing some reports. However, the first interpreter was not built until a year later for limited use. On the other hand, the first commercially available one was introduced in 1968. After that, APL started gaining popularity from the late 1960s till the early 1980s.
In contrast, these days APL is not as popular as it used to be. Despite that, development is still going. The most popular implementation of APL is Dyalog, a commercial implementation started in 1983 (yes, even the most modern of implementations is on the old side) that in recent years added useful extensions like object-oriented and functional programming, nested arrays, lambda calculus, etc. Additionally, if you are not a fan of commercial restricted use, you may try GNU APL but with fewer extensions.
Scripts of Magic
As mentioned before, APL uses a unique combination of mathematical symbols. These symbols represent polymorphic functions used to tackle a variety of problems. For example, the symbol ⌈
behaves as celling when a single integer is passed to it and as maximum when two numbers are passed to it. In addition, the symbol for the exact opposite behavior is ⌊
resulting in beautiful symmetry.
⌈ 2.4
3
4 ⌈ 2
4
Yet, the elegancy does not stop there. The circle symbol represents the Pi constant multiplies while also behaving as trig functions.
○1
3.141592654
2○○1
¯1
¯2○¯1
3.141592654
This is the case with most of the functions in APL. They consist of weird glyphs. This may seem intimidating at first glance, and it is for people that aren’t comfortable with APL’s syntax. However, it makes it much easier to look at huger chunks of logic. An impressive example is an implementation of Conway’s Game of Life, where you can see all the important logic in one line of magic. This makes many things way more elegant in some way.
Life ← {↑1 ⍵∨.∧3 4=+/,¯1 0 1∘.⊖¯1 0 1∘.⌽⊂⍵}
Simple Array Logic
A fascinating aspect of APL is the way it handles arrays. It just works exactly how I expect it to work. First off, there is no special syntax to write arrays, they are just numbers/string separated with spaces. 1 4 3
is an array of three elements: 1, 4, and 3. 'hello' 'world'
is an array of two elements: ‘hello’ and ‘world’. On the other hand, operations also makes sense. 1 2 3 + 4 5 6
sums the two arrays into 5 7 9
, which is exactly what I thought of the first time I saw a plus between two arrays. You want to sum the elements of the array? No problem just add +/
in front of the array, and it is done. A running sum? Just replace the /
with \
. More stuff like Cartesian product are also simple; just insert ∘.,
between the two arrays. This partially extends to strings since they also are arrays but of characters.
Comparison
Generally, APL solutions to algorithmic problems involving arrays in some form are much cleaner than other programming language. This is, however, not a perk of APL into itself since most array programming languages (and to a lesser extent functional ones) yields the same force of minimal simple solutions.
Problem | APL | Python |
---|---|---|
LeetCode #1920 | ⊂⌷⊢ | [nums[i] for i in nums] |
LeetCode #1979 | ⌈/∨⌊/ | math.gcd(min(nums), max(nums)) |
LeetCode #1614 | ⌈/+\(⊣-~)'('=(s∊'()')/s | max(itertools.accumulate(filter(None, map({"(": 1, ")": -1}.get, s))), default=0) |
LeetCode #14 | {+/∧\(⊃∧.=⊢)¨↓⍉↑⍵}↑⊃ | ''.join(x[0] for x in itertools.takewhile(more_itertools.all_equal, zip(*words))) |
However, it is important to realize that this is not always the case; it is completely possible to write ugly code in APL that could have been written better in other traditional programming languages. It basically depend on the problem and the approach.
For Future Wizards
- Try APL online
- Learn APL Book
- APL Wiki
- Download Dyalog APL
- Dyalog Usermeeting YT channel
- Rodrigo Girão Serrão YT channel (solves LeetCode problems with APL)
- code_report YT channel (cool person who talks about array programming)
- APL subreddit
- APL demonstration 1975