Thoughts on APL and Program Notation
A post about Arthur Whitney and kOS made the rounds a few days ago. It concerns a text editor Arthur made with four lines of K code, and a complete operating system he’s working on. These were all built in K, a vector oriented programming language derived from APL. This reminded me that I really need to look at APL after all of the language ranting I’ve done recently.
Note: For the purposes of this post I’m lumping K, J, and the other APL derived languages in with APL itself, much as I’d refer to Scheme or Clojure as Lisps.
After reading up, I’m quite impressed with APL. I’ve always heard it can do complex tasks in a fraction of the code as other languages, and be super fast. It turns out this is very true. Bernard Legrand's APL – a Glimpse of Heaven provides a great overview of the language and why it’s interesting.
APL is not without it’s problems, however. The syntax is very hard to read. I’m sure it becomes easier once you get used to it, but I still spent a lot more time analyzing a single line of code than I would in any another language.
APL is fast and compact for some tasks, but not others. Fundamentally it’s a bunch of operations that work on arrays. If your problem can be phrased in terms of array operations then this is awesome. If it can’t then you start fighting the language and eventually it bites you.
I found anything with control structures to be cumbersome. This isn’t to say that APL can’t do things that require an if
statement, but you don’t get the benefits. This code to compute a convex hull, for example, seems about as long as it would be in a more traditional language. Within a factor of 2, at least. It doesn’t benefit much from APL’s strengths.
Another challenge is that the official syntax uses non-ASCII characters. I actually don’t see this as a problem. We are a decade and a half into the 21st century and can deal with non-ASCII characters quite easily. The challenge seems to be the symbols themselves. I didn’t find it hard to pick up the basics after reading a half hour tutorial, so I think the real problem is that the syntax scares programmers away before they ever try it.
I also think enthusiasts focus on how much better APL is than other languages, rather than simply showing someone why they should spend the time to learn it. They need to show what it can *do* that is also *practical*. While it’s cool to be able to calculate all of the primes from 1 to N in just a few characters, that isn’t going to sell most developers because that’s not a task they actually need to accomplish very often (if ever).
APL seems ideal for solving mathematical problems, or at least a good subset of them. The problem for APL is that Mathematica, MathLab, and various other tools have sprung up to do that better.
Much like Lisp, APL seems stuck between the past and the future. For the things it’s really good, it is too general. More recent specialized tools do the job better. And APL isn't general enough to be good as a real general purpose language. Furthermore, many general purpose languages have added array processing support (often through libraries) that make them good enough for the things APL is good at. Java 8 streams and lambda functions, for example. Thus it remains stuck in a few niches like high speed finance. This is not a bad niche to be in (highly profitable, I’m sure) but APL will never become widely used.
That said, I really like APL for the things it’s good at. I wish APL could be embedded in a more general purpose language, much like regular expressions are embedded in JavaScript. I love the concept of a small number of functions that can be combined to do amazing things with arrays. This is the most important part of APL — for me at least — but it’s hidden behind a difficult notation.
I buy the argument that any notation is hard to understand until you learn it, and with learning comes power. Certainly this is true for reading prose.
Humans are good pattern recognizers. We don’t read by parsing letters. Only children just learning to read go letter by letter. The letters form patterns, called words, that our brains recognize in their entirety. After a while children's brains pick up the patterns and process them whole. In fact our brains are so good at picking up patterns that we can read most English words with all of the letters scrambled as long as the first and last letters are correct.
I’m sure this principle of pattern recognition applies to an experienced APL programmer as well. They can probably look at this
x[⍋x←6?40]
and think: `pick six random numbers from 1 to 40 and return them in ascending order`.
After a time this mental processing would become natural. However, much like with writing, code needs spacing and punctuation to help the symbolic "letters" form words in the mind of the programmer. Simply pursuing compactness for the sake of "mad skillz props" doesn’t help anyone. It just makes for write-only code.
Were I to reinvent computing (in my fictional JoshTrek show where the computer understands all spoken words with 200% accuracy), I would replace the symbols with actual meaningful words, then separate them into chunks with punctuation, much like sentences.
x[⍋x←6?40]
deal 6 of 1 to 40 => x, sort_ascending, index x
The symbols are replaced with words and the ordering swapped, left to right. It still takes some training to understand what it means, but far less. It’s not as compact but far easier to pick up.
So, in summary, APL is cool and has a lot to teach us, but I don’t think I’d ever use it in my daily work.
Addendum
Since writing this essay I discovered Q, also by Arthur Whitney, that expands K’s terse syntax, but I still find it harder to read than it should be.
Posted October 23rd, 2014
Tagged: programming apl typography