[HN Gopher] In Praise of APL (1977)
___________________________________________________________________
In Praise of APL (1977)
Author : tosh
Score : 87 points
Date : 2026-01-22 08:44 UTC (14 hours ago)
(HTM) web link (www.jsoftware.com)
(TXT) w3m dump (www.jsoftware.com)
| kholis_ab wrote:
| i love APL, but never ever tried it ... only watched videos of
| code_report
| abrudz wrote:
| I'll be happy to give you a live personalised intro in
| https://apl.chat or head over to https://challenge.dyalog.com/
| for an automated guided introduction (with a chance of winning
| a prize).
| jodrellblank wrote:
| https://tryapl.org/
| ofalkaed wrote:
| https://xpqz.github.io/learnapl/intro.html is a good place to
| start learning.
| singularity2001 wrote:
| Should be the ultimate final incomprehensible programming
| language for code agents
| ofalkaed wrote:
| ChatGPT is pretty good at correcting my mistakes. Give it a
| snippet of not quite working code with no explanation and it
| almost always correctly identifies what I am trying to do and
| explains where I went wrong. Its corrected code almost never
| works but its explanation of why my code failed gets me my
| answer and that is what I really want. A year ago it could not
| help me in the slightest, it has improved quite a bit. The
| biggest issue with AI and APL seems to be that it does not
| quite understand the differences between the various versions
| of APL and seems to view APL2, Dyalog and GnuAPL as all the
| same language.
|
| Edit: It probably would be useless to someone at all competent
| in APL and whose problems are more complex than their own
| failings.
| adrian_b wrote:
| True. Due to its lack of verbosity, APL is not at all forgiving
| for any substitution or transposition in its symbols, which can
| cause great differences in program output, so it is quite
| improbable for LLMs to generate a working program, unless it is
| identical with one from its training set.
|
| 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.
| skruger wrote:
| Whilst LLMs still perform weakly in APL, the situation is
| improving at pace, and giving it a "skill" to evaluate code
| makes a dramatic difference. I gave a conference talk about
| it recently (video): https://youtu.be/H_wdKeJ8gt4
| pavlov wrote:
| _> "it is quite improbable for LLMs to generate a working
| program, unless it is identical with one from its training
| set"_
|
| 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.
| ofalkaed wrote:
| >it's like APL is actually the most human programming
| language
|
| 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.
| misja111 wrote:
| > The virtues of APL that strike the programmer most sharply are
| its terseness -- complicated acts can be described briefly, its
| flexibility -- there are a large number of ways to state even
| moderately complicated tasks (the language provides choices that
| match divergent views of algorithm construction), and its
| composability
|
| 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.
| adrian_b wrote:
| Terseness is easier to remove from a programming language than
| verbosity.
|
| 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.
| misja111 wrote:
| > 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.
| creata wrote:
| > The ideal program is clear enough to be self explanatory.
|
| 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.
| misja111 wrote:
| @creata:
|
| 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.
| adrian_b wrote:
| What you say about readability is right, but it is
| something completely orthogonal to the syntax of APL
| expressions. All those things can be done in any language
| that uses the APL expression syntax.
|
| 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.
| gitonthescene wrote:
| Serious question: Why is readability so important? For me
| consistency is far more important than anything as
| subjective as readability. I'd rather be able to reason
| about a code in its own logic than feel comfortable
| browsing code without much consistency. In the end all code
| needs to be understood for its internal logic and notation
| is secondary.
| misja111 wrote:
| 2 reasons:
|
| - 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.
| gitonthescene wrote:
| In my experience code reviews are generally cursory and
| the emphasis on "readability" is more about a culture
| that seeks to treat programmers as fungible. Also
| complaints about APL's lack of readability are never
| about its lack of structure. So I took "readability" to
| mean something else as should be clear from my previous
| comment. Is your complaint about its lack of structure?
| If so would you mind elaborating?
| gbacon wrote:
| Jokesters quip "If a program was hard to write, it should
| be hard to read."
| Avshalom wrote:
| >>The ideal program is clear enough to be self explanatory.
|
| No one has ever written an "ideal program".
| runeks wrote:
| I find APL very difficult to read. Incidentally, I am told (by
| stack overflow) that the APL expression "A B C" can have at least
| four different meanings depending on context[1]. I suspect
| there's a connection here.
|
| [1] https://stackoverflow.com/a/75694187
| skruger wrote:
| Yes, it's either an array (if A, B and C are arrays), a
| function derived via the dyadic operator B, with operands A and
| C being either arrays or functions, a dyadic function call of
| the dyadic function B (A and C are arrays), or the sequential
| monadic application of functions A and B to array C, or a
| derived function as the tacit fork (A, B and C are functions).
| Did I miss anything?
| abrudz wrote:
| Yes, it can also a fork where A is an array while B and C are
| function and a tacit atop where either B is a monadic
| operator and A its array or function operand or A is a
| function and C is a monadic operator with B being its array
| or function operand. Finally, it can be a single derived
| function where B and C are monadic operators while A is B's
| array or function operand.
| boxed wrote:
| Do APL programmers think this is a good thing? It sounds a
| lot like how I feel about currying in language that have it
| (meaning it's terrible because code can't be reasoned about
| locally, only with a ton of surrounding context, the entire
| program in the worst case)
| creata wrote:
| Huh? Currying doesn't require any nonlocal reasoning.
| It's just the convention of preferring functions of type
| a -> (b -> c) to functions of type (a, b) -> c. (Most
| programming languages use the latter.)
| boxed wrote:
| Of course it requires non-local reasoning. You either get
| a function back or a value back depending on if you've
| passed all the arguments. With normal function calling in
| C-family languages you know that a function body is
| called when you do `foo(1, 2, 3)` or you get a
| compilation error or something. In a currying language
| you just get a new function back.
| creata wrote:
| Functions are just a different kind of value. Needing to
| know the type of the values you're using when you use
| them isn't "nonlocal reasoning".
|
| 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.
| bunderbunder wrote:
| It arguably depends on the syntax.
|
| 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.
| ofalkaed wrote:
| I am not good enough with APL to be certain but I think
| you can generally avoid most of these sorts of
| ambiguities and the terseness of APL helps a great deal
| because the required context is never far away, generally
| don't even have to scroll. I have been following this
| thread to see what the more experienced have to say,
| decided to force the issue.
| skruger wrote:
| It makes parsing tricky. But for the programmer it's
| rarely an issue, as typically definitions are physically
| close. Some variants like BQN avoids this ambiguity by
| imposing a naming scheme (function names upper case,
| array names lower case or similar).
| bunderbunder wrote:
| It gets me thinking about the "high context / low
| context" distinction in natural languages. High context
| languages are one where the meaning of a symbol depends
| on the context in which it's embedded.
|
| 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.
|
| A high context language would be one like Chinese where,
| for example, the character Guo 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.
| yvdriess wrote:
| And they could be 0- or 1- indexed? :P
| UncleEntity wrote:
| >> Did I miss anything?
|
| 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...
| JaumeGreen wrote:
| One of my list of dream projects that I might never have time to
| do, and so feel free to "steal" the idea, would be a eink notepad
| in where you could code in APL or similar.
|
| 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.
| icen wrote:
| You might be interested in this then:
| https://mlajtos.mu/posts/new-kind-of-paper
|
| I've not used it myself, but it appears to be the thing you're
| wanting?
| kkylin wrote:
| I've had the same dream! thanks for the pointer.
| bunderbunder wrote:
| I would probably just go for an Android eink tablet like the
| ones made by Bigme and Onyx Boox.
|
| 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.
| baruchel wrote:
| I've practiced array languages extensively myself, including for
| code golfing, and I fully understand the intellectual joy they
| can provide. But as I've gotten older, I've come to see a deep
| mismatch between what these languages present as "elegant" and
| what I find truly elegant from a computer science perspective.
|
| 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.
| bunderbunder wrote:
| On the other hand, whenever I see Python code that does
| calculations over arrays of data with nested loops instead of
| using numpy, it always takes me a distressing amount of time to
| see what the code is actually doing and that the bug is because
| of a typo buried deep in that 100 lines of code that caused one
| of the inner products to be incorrect.
| veqq wrote:
| Array languages are more conceptually simple. What do you
| concretely mean to mock with:
|
| > 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
| t-3 wrote:
| It's not like array languages don't do any optimizations...
| Denying the programmer the ability to be clever by manually
| writing loops makes some things easier and simpler for the
| compiler as well.
| meken wrote:
| I enjoyed the FBAPP acroymn. There should be a modern day
| equivalent.
| kstrauser wrote:
| I'd like to play with an array language because I've never used
| one. I don't want to pay for it; this is just for fun and as an
| experiment. I also want to run it locally in a shell, writing it
| in a local editor, not working in a web UI. And while popularity
| isn't everything, and none of these are exactly Python levels of
| widespread, I also don't want to find myself learning a cool one
| along with 3 other people in the world and then find out all
| other array language programmers do things completely
| differently. (Analogy: I don't want the equivalent experience of
| picking Haskell as my first ever PL.)
|
| 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?
| vegabook wrote:
| there's also a Forth-meets-APL project called uiua
| [https://www.uiua.org/]
| kstrauser wrote:
| That may require a little more mental bandwidth than I can
| summon right now. It looks incredibly cool, though.
| invalidOrTaken wrote:
| I haven't tried the others, but J meets all those requirements.
| RodgerTheGreat wrote:
| Yep. J has a small userbase, but it isn't fragmented into
| dialects like K or even APL, J uses ASCII characters instead
| of requiring a custom font/keyboard layout, J is FOSS, J has
| extensive learning materials, and J is reasonably batteries-
| included and suitable for making practical nontrivial
| programs.
|
| I like K better than J aesthetically, but it's harder to
| recommend to beginners due to the fragmentation of the
| ecosystem.
| kstrauser wrote:
| I keep getting nudged in that direction. I'll check it out,
| thanks!
| skruger wrote:
| I faced exactly this situation a few years ago - I went with
| APL as the "OG", but it probably doesn't matter that much.
| Learning k or j once you know APL is much easier. I wrote a bit
| about this (apl and k)
|
| https://xpqz.github.io/learnapl
|
| https://xpqz.github.io/kbook
| kstrauser wrote:
| Oh, perfect. Thanks for the links!
| i-blis wrote:
| J is, within the APL family of languages, the one I have always
| found the most useful. I reach for it as I used to reach for my
| HP calculator in the past, to quickly compute or numerically
| model things. I always have it running in a terminal window.
|
| 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.
___________________________________________________________________
(page generated 2026-01-22 23:01 UTC)