In 2021, I made a prototype calculator designed for iPad and Pencil and wrote four essays called "New Kind of Paper" describing this concept. The video demonstration of the prototype [Demo] sums up pretty well how it might be used.
In 2024, Apple released Math Notes, which implements this concept for standard math notation. My "review" of it is at [MathNotes]. In short, it is currently a preview of a damn great tool, but its future depends on notation and expressivity.
APL is a language from 2066, created in 1966. While its semantics make more sense now due to machine learning, syntactically it remains alien to most people. Backus' FP/FL and Iverson's J are more approachable to current programmers, but still not there. In New Kind of Paper, I created a tiny language called Fluent, which is nowhere near the ambition of any language mentioned, but it is intentionally designed to be handwritten. A week ago, I open-sourced it. [Fluent]
There is plenty of work left to do, but it is a good start.
[NKoP]: https://mlajtos.mu/posts/new-kind-of-paper
[MathNotes]: https://mlajtos.mu/posts/new-kind-of-paper-5
[Fluent]: https://news.ycombinator.com/item?id=46649223
[Demo]: https://youtu.be/y5Tpp_y2TBk
Thanks for coming to my TED talk.
I’ve not used it myself, but it appears to be the thing you’re wanting?
It looks like there are a few APL implementations for Android out there, or you could use a remote editor or terminal app to access an APL implementation running elsewhere.
Sure, realizing that the foobar of x is nothing more than the transpose of the 15th foo of x, combined via an inner product with the 7th bar of x raised to the power of baz, can be an ineffable intellectual delight. But actually computing that, rather than writing a “boring” loop, feels horrible to me. To my eyes, a “boring” piece of code written by Dijkstra in some Algol-like language contains more beauty than all these dazzling sleights of hand that hide zillions of loops under the rug while pretending that the actual computation doesn’t matter.
> realizing that the foobar of x is nothing more than the transpose of the 15th foo of x, combined via an inner product with the 7th bar of x raised to the power of baz
Contrary to popular belief, its learning curve isn't steep. I once introduced it to high school freshmen who had no real experience with programming. I recommend the series of booklets by Kenneth Iverson himself: Arithmetic, Algebra, Calculus — there is even a Concrete Mathematics companion to accompany the book of the same name by Graham, Knuth et alii. They're all available for download on the site.
Edit: It probably would be useless to someone at all competent in APL and whose problems are more complex than their own failings.
What I have said matches exactly what another poster said about his experience in using a LLM with APL: "Its corrected code almost never works".
The LLM recognizes the problem that must be solved by the code, but it fails to generate the right APL symbol string.
I doubt that here a coding agent that attempts to verify the generated code by compiling it can help, because the LLM will generate eventually some syntactically-correct symbol string, but which will implement a different function than desired.
Only a complete feedback loop, with a battery of varied tests for the executable program produced by the generated code, which can verify if it really implements the desired functionality, can be used to filter the results for a working program.
APL is greatly superior to almost all programming languages that are popular today, for writing expressions involving arrays (this includes expressions that do not involve arrays in other languages, but which could be made simpler by using arrays in APL).
However, the original APL has defects, due mainly to the fact that it was an incomplete programming language, e.g. when compared to the other contemporaneous IBM language, i.e. PL/I.
What one needs is a programming language with modern program structures, data types and data type definition facilities, but also with an expression syntax matching the power of APL expressions.
The fact that in 2026 most programmers continue tho write "for" loops for handling arrays, instead of using array expressions like it was possible in 1966 in APL, 60 years ago, seems an aberration of history. Even in the 1966 PL/I one could use array expressions, even if only expressions that were much simpler than those of APL.
Using symbols instead of keywords, like in APL, is not cryptic for anyone who uses such a language regularly. It is cryptic for those who have not used them. The English-based keywords are somewhat less cryptic only for English speakers, and even for them they can be misleading before they learn their correct meanings.
This is a fascinating result. In some sense it’s like APL is actually the most human programming language, despite being one of the most difficult for ordinarily trained human programmers to pick up.
As an incompetent programmer who is far more comfortable with even the most experimental and abstract literature than any of the "easy" programming languages, I agree with this.
Edit: I was going to fix that sentence, but it is a good example of what thinking about programming languages does to my brain. The idea of a context free human language is alien, thinking in such absolute and concrete terms is weirdly abstract.
This topic tends to bring up a few, like APL itself, J, K, and BQN. Given those (soft!) constraints, what’s the one I want to start hacking around with?
I like K better than J aesthetically, but it's harder to recommend to beginners due to the fragmentation of the ecosystem.
It’s a continuum, so English is typically considered low context but it does have some examples. “Free as in freedom versus free as in beer,” is one that immediately comes to mind.
À high context language would be one like Chinese where, for example, the character 过 can be a grammatical marker for experiential aspect, a preposition equivalent to “over” “across” or “through” depending on context, a verb with more English equivalents than I care to try and enumerate, an affix similar to “super-“, etc.
When I was first starting to learn Chinese it seemed like this would be hopelessly confusing. But it turns out that human brains are incredibly well adapted to this sort of disambiguation task. So now that I’ve got some time using the language behind me it’s so automatic that I’m not really even aware of it anymore, except to sit here racking my brain for examples like this for the purpose of relating an anecdote.
I would bet that it’s a similar story for APL: initially seems weird if you aren’t used to it, but not actually a problem in practice.
And it's not like curried function application involves type-driven parsing or anything. (f x y) is just parsed and compiled as two function calls ((f x) y), regardless of the type of anything involved, just as (x * y * z) is parsed as ((x * y) * z) in mainstream languages. (Except for C, because C actually does have type-driven parsing for the asterisk.)
Another way to look at it: languages like Haskell only have functions with one argument, and function application is just written "f x" instead of "f(x)". Everything follows from there. Not a huge difference.
In an ML-like syntax where there aren’t any delimiters to surround function arguments, I agree it can get a little ambiguous because you need to know the full function signature to tell whether an application is partial.
But there are also languages like F# that tame this a bit with things like the forward application operator |> that, in my opinion, largely solve the readability problem.
And there are languages like Clojure that don’t curry functions by default and instead provide a partial application syntax that makes what’s happening a bit more obvious.
Derived operators?
And, 'A B C' as an array isn't valid (ISO) APL but an extension, the 'array syntax' only covers numbers and the parser is supposed to treat is as a single token.
Your useless information of the day...
But maybe later, if you allow, I will contact you!
I had an introduction to APL in university and what I absolutely hated was this terseness. I guess when you're a mathematician APL is more natural but to me, as a programmer, I much prefer to have some extra verbosity to make my code more (human-)readable.
You can use a source preprocessor to enable you to write APL programs by using keywords instead of any symbols that you do not like. You can also use a source preprocessor to expand any traditional APL source, by converting symbols into keywords, so that it will be easier to read for you.
Using symbols instead of keywords is a minor feature of APL, which was inherited from the standard mathematical notation, from which APL was derived.
The important features of APL are the expression syntax and the set of available operators, not the symbols used for them.
Moreover, if you have difficulties in following complicated expressions, you can always break them in smaller subexpressions.
When someone presents an "incomprehensible" APL program, they show a huge expresion without comments.
A decent APL program, like in any other programming language, would need good comments, but here comments are frequently desirable at the level of subexpressions.
I guess that might be true for APL, for other programming languages that's not true at all. The ideal program is clear enough to be self explanatory. Of course there might be some implementation choices that need a comment. Or in some cases the problem is so difficult that this is not possible.
But readability should be the goal and most of the time this is feasible without comments. E.g. by using descriptive variable and function names. And by breaking up your program into logical and cohesive parts, using functions, objects, modules or whatever construct your language is offering.
That depends on what you're doing and who you expect to be reading your code, doesn't it? Sometimes what the human needs and what the computer/runtime needs are too far apart.
- in a corporate environment, your code is going to be read by many other people than just you. Your team mates, the guy after you left etc.
- also, by making your code more readable, you're making your own life easier as well. You might have thought at first that your code was fine, but by structuring it properly and possibly removing some redundancy, you might find that you were overlooking some things.
If one doesn't know the programming language, no program will be clear, if they do know the language, any simple and well-written program will be clear. Clarity is a property partially of the reader and partially of the program, not the programming language.
For someone who knows the APL symbols, what an APL expression does is self-explanatory. Someone who does not like symbols can replace them with keywords, that does not change the APL syntax.
The only problem is that you can write a very complex APL expression, which may be equivalent with a page of text in other programming languages. In such cases it is still easy to see what the expression does, but its purpose may be completely obscure, e.g. because you are unfamiliar with the algorithm implemented there, so you need comments explaining why those operations are done.
In many cases you can do like you suggest, you can split a very big expression in many subexpressions and store intermediate results in temporary variables to which you give names that are suggestive for their purpose, instead of adding comments.
However, I see this solution as inferior to just providing short comments for the subexpressions, which give you the same information as the intermediate variable names, but without forcing the compiler to choose an expression evaluation strategy that may be suboptimal.
I completely agree that "The ideal program is clear enough to be self explanatory".
However, regardless of the programming language, it is very frequent to see programs where it is clear what is done, but you cannot understand why that is done. In most cases you already have precise expectations about what the program should do, but you see that it does something else, without any apparent reason. In many cases, the program does certain things because there are certain corner cases that are not at all obvious from the existing system documentation, or worse they are not documented at all anywhere, except for the presence of a mysterious program section that handles them. Even worse is when such mysterious program sections are present only because of some historical reasons, which are no longer true, and now the code is superfluous or even harmful.
These frequently encountered situations can be prevented only by adequate comments about the purpose of the code, regardless how self-explanatory is what it does.
No one has ever written an "ideal program".
yes I agree. In case of APL, if your readers are mathematicians, I guess it could well be the language of choice.
And yes like I already said, self explanatory code is not always possible but more often than not it is. It just takes a little extra care and thought.
APL was born as a mathematical notation, pertaining to the blackboard, so it makes sense to write it using a writing implement. Its terseness would make it ideal for the handwriting world, it's REPL implementation would give quick feedback loops, you could move around input and output streams.
You could be in a sofa, writing the solution, expending most of your energy thinking, not writing, once you got used to the new way of thinking and the vocabulary.
If you haven't tested any array language I would recommend you try to solve things using one, and check existing solutions so you can see how to think differently. Some problems are naturally easier with this approach, some are harder.