By using abstract symbols, it encourages one to skip the internal verbalization and go straight to the concept. Pretty neat.
But in the article, they use symbols that I don’t have on my keyboard. I guess one would learn the combination for such symbols and become fluent to the point that it didn’t matter. For example, I don’t think of the individual letters when I’m typing.
Although my highschool typing class strongly encouraged doing so. I believe that was more for maintaining a rhythm, however.
Earlier this year I took a deep dive into APL (something I'd been meaning to do for a while). With Dyalog APL and the APL mode in emacs, typing these things in is pretty easy and becomes natural if you're already a touch typist.
For instance, iota is just `.i`, rho is `.r`, etc. Some are more natural (like that) others are arbitrary but logically consistent, like take and drop are next to each other on the keyboard.
After a few days I felt like I could type most programs without having to think about where keys were. Admittedly, I've lost it all now since I haven't touched it for a couple months. If I actually stuck with it for more than the 4-6 weeks I did I imagine I wouldn't have lost it so quickly.
I understand that the compactness is a feature, and I don’t have any gripes with the symbolic notation personally, I just think a more verbose notation might avoid turning people off too early. By starting from familiar territory, you can get people accustomed to a new style of thinking before switching to a more compact syntax. Lots of new programming languages borrow syntax from familiar mainstream languages in order to reduce friction for beginners and experts alike.
Heck, as long as we’re on the subject, I’d take a symbolic notation that used small icons or emoji as a sort of middle ground—at least then they might be more mnemonic. For instance, there’s nothing about ↑ that suggests “take” to me, or ⍉ “transpose”, but I’d have a good guess at what these icons mean, and they could remain legible at fairly small sizes:
Why? Because when you aggressively use infix notation, there is operation order precedence ambiguity which is not there in polish (functional) notation. The pipeline idiom creates a "main line of computation" which really covers about 80% of use cases. I'd rather not have to remember so many things (I am getting old) and some notations are far clearer than others.
Music notation is a form of assembly language in which the original compositional ideas are expanded and flattened out into reams of tiny instructions for a "virtual machine": an abstraction of a musical instrument.
Nothing in music indicates semantic concepts like "this is motif M3 from the first movement, but transposes into a minor key, and played backward at half tempo". It's all just expanded into notes, which are like micro-instructions for the violin or oboe.
The music composer, when engraving notation, rarely invents any new symbols. If so, in a modest quantity.
In even small scale software engineering, the symbols unique to a given software system outnumber those in the programming language. We develop software by creating large dictionaries of new identifiers, such as functions and types. These symbols, which can number in the thousands and beyond, cannot have one character names, or there will be chaos.
The main challenge is understanding a program's own identifiers, not those in the programming language.
Terseness in the programming language helps at the microscopic level. The leaf terms of the program's syntax tree become more compact. The advantage of this in the overall context of making a big program is modest and has diminishing returns. Giving the core functions of a language short names, say from around two to six characters, goes a long way toward bringing about a useful level of terseness.
What also helps understanding is giving meaningful names to intermediate values. A pipeline of 13 operations is hard to understand, whether their names are one-character glyphs or 4-8 character words. If it's broken into, say, three smaller pipes, the first two of which are evaluated into variables with meaningful names, it will be helpful.
So that is to say, we shouldn't be cramming so many open-coded steps into a computation that they need one character names in order to fit into a reasonable space on the screen.
This is the problem with APL programs and programmers: failure to decompose complex operations into small functions with clear names.
I don't care that you can make some cool operation by stringing together seven letters. I am not impressed. What I don't want to see is you copy and pasting those seven letters all over the place whenever you wish to invoke this cool operation. If I will have to maintain that, I would really appreciate it if that string of seven letters appeared in one place as a definition, and had a nice ten-letter name, which is then used in all the other places where that operation is required even though (horror of horrors) it is 42% longer!
And, no, do not be giving it a one-character name using some Greek or Japanese symbol not yet claimed by APL. Do you really want your maintainers to have to make flashcards of the program's identifiers and do spaced repetition night after night?
> Terseness in the programming language helps at the microscopic level.
And even more at the sub-system level.
In practice I've found I can efficiently understand and work with chunks of code that I can immediately see + a dozen or so helper functions + 4-5 in-context/highly contextual other functions.
Everything else exists only at a very high level.
In c# I can see around 4-5 functions on my dual screens.
In APL it is closer to 100 functions.
> A pipeline of 13 operations is hard to understand, whether their names are one-character glyphs or 4-8
I don't think this is true and thankfully significantly fewer developers believe this is true than they did 10 years ago thanks to linq/streams.
By day I'm a c# dev and most of my colleagues can easily understand a long linq chain.
The mental complexity in linq almost always comes from heavily nested linq rather than from the number of operations.
> This is the problem with APL programs and programmers: failure to decompose complex operations into small functions with clear names.
The clarity of a name comes from the context, density, domain, and usage.
For example a single letter variable in a 5 line loop is often crystal clear.
So is a 2 letter variable used consistently hundreds of times throughout a code base.
So is a single word only used once that comes from the business domain.
I've found APL allows you to get rid of many pointless intermediate names and in doing so it increases the clarity of the code.
In a language like c# this can cause significant and problematic code duplication - in practice in APL it's not a big issue.
tranpose=:⍉
take:=↑
index=:⍳
each=:¨
done, now I can write (⍉↑x⍳¨x) as (transpose take x index each x)
But the entire idea of APL is notation as a tool of thought.
Would you write read your maths as five plus twenty is equals to twenty five or 5 + 20 = 25?
Would you rather read music with it's musical notiation
or quarter note at middle C, quarter note at middle E, etc?
The entire idea of APL is that we read and write algorithms the way we read mathematical and musical notes.