229 comments

[ 3.1 ms ] story [ 245 ms ] thread
I intend to learn an APL at some point. I'm an avid listener of the Array Cast podcast [0]. Can't say I u derstand all of what they talk about but I definitely feel like APL has its place for number crunching.

[0] https://www.arraycast.com/episodes

I love the keyboard. Wouldn't it be nice if modern programmers had some more symbols at their disposal?
Not really but if you are up to it, Julia allows for it.
I am using a Stream Deck for that. Should have bought the largest one, but even the medium size on is quite useful via nested menus. Here are some symbols I am using for a formalisation in Isabelle currently: ∀∃⊤⊥𝔇𝔄≽⇒𝒰υτ↣𝟭‹›∅×∈⊆
You could probably get it working on any keyboard with Autohotkey on Windows

Ahk can override keyboard button presses with just about anything and you can use a layer key as a modifier

xmodmap in Unix/X11 also.

But I'd really like a language that comes with its own keyboard :)

I mean, other people should be able to edit my code.

Provide a copy of your ZMK keymap file and a recommended build target alongside your software (lol)
I think it's crazy that we limit programming languages to using ASCII in 2022. Yes, I understand the chicken-and-egg issues of input, but it still seems like we're limiting ourselves as developers if we don't make use of a richer symbology. I know Raku supports some Unicode operators and Guy Steele's Fortress language also supported non-ASCII symbols so it is possible. But I'm not holding my breath. This is just one old man's crazy opinion.
We do. Look at Scala. Almost no limitations here.
AFAIK Fortress did not actually support non-ASCII symbols in the code. What the Fortress team did is have a display layer that was fed a list of symbols using ‘\BigSum’ style ASCII and then merely displayed a selected Unicode symbol in the editor.
Ah, thanks. It's been a while since I looked at the Fortress papers.
Julia supports most unicode characters for function and variable names (and operators), so you can write, eg, "∑(x,µ) = x ⊗ µ" and it won't complain.
JavaScript, Java and C# all allow Unicode characters as identifiers.
"Wouldn't it be nice if modern programmers had some more symbols at their disposal?"

Emacs lets you display arbitrary text as any symbol you want, and you can also map your keyboard to generate that text with any keystroke of your choice.

So the result is the same, without needing language support for the symbols you want to use.

I've done this with the lamba symbol and symbolic logic symbols when editing LaTeX files in emacs. It works great.

Read up on the Compose key. ASCII-based keyboards also don’t not prevent Chinese/Japanese/Koreans/etc. from writing their scripts with them. Entering Unicode symbols by keyboard is not a problem. Few programming languages support them for operators though.
I’ve been dabbling in this, and created my own keyboard layout to include all kinds of math characters using the right Alt key for level 3 and level 4 shift. Also replaced caps lock with the compose key. Didn’t take too long to get accustomed to it since it’s a corruption of the Greek keyboard layout (which is laid out similar to QWERTY).

I haven’t had the audacity to use it in production code, but it’s interesting to play around with and great for quick note taking or hacker news comments. (Sadly I’m on my phone right now to not make use of it for this comment)

APL looks like a lot of fun, and I've tried to get into learning it for a while, but it's a shame that the most popular implementation is proprietary, and GNU APL is a dialect which is not as featureful and a separate dialect of APL unto itself, so it's not as though you can write a reasonably sized APL program with Dyalog and then expect it to work in GNU APL.
You can download a copy of Dyalog for free, if availability is the issue.

If it's licensing/a desire to use open-source software, perhaps taking a look at its close relatives of J, or BQN, would be reasonable?

* Dyalog https://www.dyalog.com/download-zone.htm * J https://code.jsoftware.com/wiki/System/Installation/J903/Zip... * BQN https://mlochbaum.github.io/BQN/index.html

All of the languages and implementations have their differences, but they are all driving toward the same ultimate goals.

"The GNU APL interpreter is an (almost) complete implementation of ISO standard 13751 aka. Programming Language APL, Extended." [1]

GNU APL is closely following the APL2 standard [2], Dyalog has lots of (proprietary) extensions.

APL does not have its roots in the FOSS world, all the more the efforts to provide and maintain a powerful, free option here are to be supported. It is not self-evident that there are always free software alternatives available.

[1]: https://www.gnu.org/software/apl/

[2]: https://www.ibm.com/downloads/cas/ZOKMYKOY

Oh, I didn't know that. Looks like I was completely wrong about GNU APL. Thanks for the links.
The standard for APL2 is quite old and doesn't reflect the state of commercial APL at all (Dyalog is the only one with significant development now but APLX and APL+Win kept it going through the 90s). For example, GNU doesn't have control structures so you are expected to program with the branch statement, APL's version of go-to. It also has various extensions of its own, including some that are based on Dyalog but not compatible. It's the only dialect that I would recommend against; I believe April, NARS2000, and dzaima/APL are all better despite various issues.
I highly recommend trying BQN [0]. It's a lot of fun indeed. It retains the array programming paradigm but modernizes a lot of things -- and has excellent documentation (but not much in terms of ecosystem, yet). The main implementation is GPLv3.

[0]: https://mlochbaum.github.io/BQN/

Suppose you have a couple graphs, represented by adjacency matrices (A and B) whose cells represent travel times or distances or some other notion of cost. Assuming their dimensions are compatible, and that the columns of A correspond to the same nodes as the rows of B, then

  A ⌊.+ B
will produce a new adjacency matrix (call it C) where each c_ij is the minimum traversal cost from node i to node j. For example, if A represented driving times from all cities in NY state to all airports in NY, and B represented direct flight times from all NY airports to all CA airports, then our result would be the minimum travel time (ignoring parking and security) between any NY town and any CA airport.

The sequence `⌊.+` is an inner product chosen specifically to achieve this effect, with addition where multiplication would normally be, and ⌊ (min) where multiplication would normally be.

Notice that it took me longer to give this under-caffeinated explanation of what is going on than to write the code.

So, if I understand correctly, your APL code translates to the following Mathematica code:

    Inner[Min, A, B, Plus]
where B = Transpose[A] ?
If anything, you'd need B = Transpose [B] as A and B are not related.
Can APL be used for symbolic computations, like Mathematica or Sympy, or is it practical just for numeric code, like Matlab or Numpy?
Some tools for symbolic computations have been written in APL, but APL doesn't provide such capabilities out of the box.
> The sequence `⌊.+` is an inner product chosen specifically to achieve this effect, with addition where multiplication would normally be, and ⌊ (min) where multiplication would normally be.

Sorry, it is early for me too. I am wondering if there is a mistake here. Do you mean that addition is where multiplication would be and min is where addition would be?

The regular inner product would be

  C_ij := \sum_k A_ik B_kj
and the modified one is

  C_ij := \min_k (A_ik + B_kj)

?
(comment deleted)
I presume so.

Note that this pseudo-code is very nearly valid Julia code (with my package):

    @tullio (min) C[i,j] := A[i,k] + B[k,j]
Sorry but to me this looks like a cool language to play code golf, but a terrible language to use in production. It feels like obfuscating your own source code.
This is an executable math. Consider the program a mathematical expression - or a set of them - which produce useful values.
Yes, multiplying graph adjacency matrices over a min-tropical semiring produces shortest paths. APL supports this syntactically, but how does it function in the real world? What if the matrices are extremely sparse, like almost all real world graphs are? Syntax is the easy the problem. The hard problem is having very sparse graphs with billions of nodes and many billions of edges. How is a square matrix going to deal with that? Sparse and hypersparse graph computing is hard, which is not syntactically relevant.

Python does not have this terse a syntax, but it gets very close with multiple bindings to the SuiteSparse GraphBLAS Hypersparse graph processing libraries, which intrinsically supports sparse graphs and a very large number of operators, including the tropical min/max ones. Suitesparse doesn't provide syntax (that's the easy part), it provides the hard part, sparse and hypersparse data structures and very complex dynamic, parallel graph processing optimizations including JIT compilation of GPU accelerated operations.

Here's a notebook that shows your shortest path example using Python and the GraphBLAS. While it's a trivial example, it can scale the the largest graphs possible to use today using SuiteSparse:

https://github.com/Graphegon/pygraphblas/blob/main/demo/Intr...

NB: I should clarify I'm not advocating for Python's syntax in particular vs APL, I'm saying that syntax is not the hard part of any particular problem, especially when it comes to sparse graphs. There are also other binding to GraphBLAS like Julia that are quite nice. I do appreciate that APL does elgantly permit the notion of graph operations with linear algebra.

This is basically floyd-warshall, right?
Hm wait floyd-warshall is subtly different from regular matrix multiplication with (+, *) replaced with (min, +). We're accumulating into the existing matrix so the order of loop iteration matters, it has to be {k, i, j}. As such I'm not sure how

   C_ij := \min_k (A_ik + B_kj)
would work to give all pairs shortest path, since in floyd-warshal the results of C[i][j] at iteration k depend on C[i*][j*] for k-1 being computed, which is not true for the above where C_ij can be computed independently of all others.

It seems like it _is_ possible to easily express APSP via an inner product with (min, +), but it's less efficient than floyd warshal. Whereas floyd warshall asks "What's the shortest path from i to j using vertices in {1..k}", if you instead ask "what's the shortest path from i to j of length at most k" and then use repeated-squaring you can get the answer in n^3 lg(n). See

http://users.cecs.anu.edu.au/~Alistair.Rendell/Teaching/apac...

https://cse.buffalo.edu/~hungngo/classes/2004/531/notes/floy...

https://resources.mpi-inf.mpg.de/departments/d1/teaching/ss1...

https://www.cs.utexas.edu/~ecprice/courses/randomized/fa15/n...*

The tutorial of the recently posted BQN variant of APL (https://news.ycombinator.com/item?id=33180842) is super approachable and written so nicely, that I couldn't resist being drawn in - I highly recommend checking it if you're even slightly "APL-curious". The first part is at: https://mlochbaum.github.io/BQN/tutorial/expression.html
BQN is great, but I rarely get to use it for anything... useful. I hope the ecosystem and tooling around bqn will get better in the future. I would like to see something like what dyalog is to apl for bqn. A jupyter notebook style ide+repl (maybe a bqn for of RIDE), libraries for common scripting tasks, embedding (a la lua) in more languages, maybe even a way to compile to libs so you can call bqn code from other languages. I'd definitely use it more if it was open to more use cases.
Have some experience with J, would like to comment.

> A jupyter notebook style ide+repl (maybe a bqn for of RIDE)

J terminal looks pretty close.

> libraries for common scripting tasks

There are phrases (see www.jsoftware.com), but for many tasks it seems not many libraries are actually needed.

> embedding (a la lua) in more languages, maybe even a way to compile to libs so you can call bqn code from other languages

There is a way to call C from J and vice versa; not too convenient maybe... but still quite possible. APL languages don't benefit much from compilation, J interpreter is very fast.

> APL languages don't benefit much from compilation

Is the idea because most the action is in already compiled datastructure manipulations, in the standard library, specified by the terse source?

The operations on "entire arrays at once" don't benefit much from compilation, because the interpreter overhead is amortized across the size of the array.

For "one potato two potato" scalar code code with lots of branches and control flow, compiled will always be faster because each little op has overhead and a compiler could optimize it away.

A sufficiently smart interpreter or JIT could theoretically optimize this away too, but as far as I know no APL (or APL-like) language uses anything like a tracing JIT, instead they have historically focused on optimizing idiomatic expressions so "typical" code is faster.

> APL languages don't benefit much from compilation

Sorry, but this is nonsense. APL tends to spend all its time waiting for memory, because it fuses nought. And it benefits as much as anybody else from things like common subexpression elimination and loop-invariant code motion. APL implementations appear to be fast because of a few extenuating factors:

1. C compilers kind of suck, and c kind of sucks for writing fast code, yet it is the de-facto standard, so it is what things are compared to.

2. Developers of apl implementation care about and prioritise performance.

3. In comparison with languages such as python, and in particular their popular implementations, apl spends very little time on dispatch.

What kinds of numbers do you expect here? It's really only arithmetic that's memory-bound, even something like a scan or compress/filter does a fair amount of CPU work and wouldn't benefit that much from fusion (if you even can fuse compress). And with fewer loops I don't think loop optimization is as relevant. I think a factor of 2 is the median kind of improvement I'd expect from a compiled SIMD APL on array programs? Which is a long way from the 10x or so you get by adding a JIT to other dynamic interpreted languages, and likely harder. I would describe that as APL not benefitting much from compilation; maybe you wouldn't.

(I've written some about what array compilation would mean at https://mlochbaum.github.io/BQN/implementation/compile/intro...)

I think a factor of 2 is quite significant, but I also think you may understate the advantages of compilation. I do agree the benefit is prone to be less than for a language like python.

Regarding scans (filter is a type of scan, howbeit easier to implement than the general case), there is in general an annoying work-span discrepancy, which bodes ill for contemporary computers with their finite parallelism. I would buffer heavily here, but fusing the scan with its input allows for the use of a work-efficient implementation, spending all latent parallelism on generating more inputs.

When I speak of loops, I am including any usage of rank (incl. implicit); in this respect, apl is chock-full of loops. Some loop optimisations may be obviated, of course, because of referential transparency, but others arise in their place. Take for instance some recent work[0] done on futhark: rather than parallelise an already in-place algorithm, they had to in-place an already parallel algorithm!

Two more points:

A problem may be bound by memory latency. I spent some time tuning j's I. recently, and it does many searches in parallel (4 for a small search space, 12 for a large one, iirc), but it is still bound by latency. If I could fetch a pivot corresponding to the first cell of y, and then generate the next cell while I wait, I would make better use of resources.

A compiler results in more transparent performance characteristics. When I target an interpreter, I must write my idioms and special combinations in exactly the way it expects, else nothing will happen; a compiler will care much less about exact phrasing. Similarly, like I mentioned, you get licm and cse for free, rather than needing to do them by hand.

0. https://futhark-lang.org/blog/2022-11-03-short-circuiting.ht...

Feels like a pretty idyllic view of compilers? I guess I agree that there's more than a factor of 2 in instruction latency versus throughput, but I don't think a compiler can use the entire gap. For a quick check, I measured 1.82 instructions per cycle to compile ~0.3MB of source in BQN (the compiler's a very array-oriented program for those unaware) and 1.38 ipc on ~1.7MB where caching's worse. The maximum is probably somewhat less than 4 since not all instructions fit 4 to a cycle; on the other hand, BQN primitives are probably already doing some things that are throughput-inefficient to use available parallelism better. Fused compiler output definitely wouldn't include as many loop counter and load/store instructions.

Some of the problems you mention, especially special combinations, can be addressed by a bytecode compiler that ultimately defers to an interpreted VM.

The binary search interleaving seems like exactly the kind of thing that APL interpreters can do to close the gap with compilers. "generate the next cell while I wait" sounds difficult in general: instruction reordering only goes so far, so if the binary search loop needs many iterations, then only part of it can overlap with other code (barring some compiler intervention that I'd categorize as fanciful if the loop length isn't known). That other work could also be polluting the cache.

Your binary search work is definitely interesting; I found the code and will be studying it as this is something I've been wanting to address better in BQN. Mind if I email about this? I implemented a different solution to high latencies for large searches in Dyalog, which is to partition the array y (searched-for values) by a single pivot from x and recurse. See the last paragraph at https://mlochbaum.github.io/BQN/implementation/primitive/sor....

> For a quick check, I measured 1.82 instructions per cycle to compile ~0.3MB of source in BQN (the compiler's a very array-oriented program for those unaware) and 1.38 ipc on ~1.7MB where caching's worse

It's not really clear to me what this is measuring, and whether that thing is interesting. I care about throughput as measured in widgets per unit time, not instructions per unit time; the contribution of a compiler may not only be in instructions per unit time, but also instructions per widget.

> Some of the problems you mention, especially special combinations, can be addressed by a bytecode compiler that ultimately defers to an interpreted VM.

Sure. But aside from implementation effort, that seems monotonically worse than a compiler targeting machine code.

> if the binary search loop needs many iterations, then only part of it can overlap with other code (barring some compiler intervention that I'd categorize as fanciful if the loop length isn't known)

What interventions? FWIW I think the main limitation is (architectural) registers (plus rob/rename, of course), but you can balance around that by putting multiple _dependent_ search iterations, and leaving enough time for them all to finish.

Also: I think it's probably good to have at least a rough idea of how many iterations things are going to take, and am vaguely planning to specialise on order of magnitude of each dimension (plus exact value when small). Knowing how big things are also gives you a fairly good idea of what is going to pollute cache (conservatively assume that random accesses are uniformly distributed) and by how much.

> Mind if I email about this?

Feel free! elronnd@elronnd.net. FWIW I think the gather hammer, where supported, is probably ideal--I benchmarked it, and it lost, but I was on AMD hardware at the time, which is quite abysmal in that respect; intel seems to be much better, especially with avx512--and that leads to much more straightforward code.

> I implemented a different solution to high latencies for large searches in Dyalog, which is to partition the array y (searched-for values) by a single pivot from x and recurse.

I figured it was doing something like that. Was thinking about implementing something similar, but vaguely hoped that if the buffers were large enough and I could keep them filled, it would be possible to avoid the overhead of partitioning and of scattering results. Also the option, depending on relative sizes, of preprocessing x, producing e.g. a b-tree or eytzinger. Fairly low priority, so I've not yet looked too closely.

There is a lot of development happening in the area of APL-insipred programming languages.

I've spent far too much time working on an APL dialect that allows you to combine APL with imperative structures at the same time. I really need to document it better though. https://aplwiki.com/wiki/KAP

Then there is April, which is a very neat version of APL that is implemented in Common Lisp. It allows you to miss Lisp arrays with APL arrays, giving you the best of both worlds. It's very functional even now: https://github.com/phantomics/april

And of course, BQN is a new language that takes a lot of the good ideas from APL but also changes a lot of the symbols. It's a very nice language: https://mlochbaum.github.io/BQN/

What about using like a Wacom drawing tablet in order to interact with APL?

I've never tried any of the Iverson-verse languages but the non-ascii inputs seem daunting and cumbersome.

Most editors let you use an input prefix, so typing `y gets you ↑ for example. Makes it a lot easier
Most typing in the world today is done on virtual keyboards on touchscreens.

I’ve always hoped someone would make an APL for iOS and Android. The code density and use of symbols seems like a good fit for small touchscreens.

Came here to say exactly this -- an APL-like notation + programming environment would seem to be a great way to program on a tablet + stylus. I'd love a notebook environment where I can mix equations, doodles, executable code, & their output.
What about using gesture recognition on a smartphone or tablet? It could become a useful portable calculating/coding app that doesn't need much typing. I know there are J apps and web APLs available, but not gesture ones that I know of.
The only time I see APL is each year during Advent of Codehttps://adventofcode.com/ – APL users always pop up and manage to solve the most complex of tasks with about ten symbols versus everyone else's 50 lines of Python :-)
I tried to do AoC in sed one year. Didn't get all the way through. Real turing tarpit sed is. My solutions had the readability of APL and the brevity Java.

Mistakes were made.

I'm not sure if I should be in awe or feel sorry for going to that level of programming masochism in one's spare time. Probably both.
I enjoyed russ cox's advent of code series using rob pike's ivy (https://github.com/robpike/ivy), an apl-like calculator

https://www.youtube.com/playlist?list=PLrwpzH1_9ufMLOB6BAdzO...

This is what got me and my friend into APL-likes. My friend even made an APL-like towards the end. I assert that APL is one of the main, definitional pillars of programming languages, the way Lisp and C and Prolog are. It is extraordinarily easy to build an APL with scalar and vector support -- once you start thinking about higher-dimensional data structures, though, it is the ergonomics and the design that become subtle and tricky. (Ivy, in particular, does some questionable things at with multi-dimensional matrices.) Also, if you think of APL operators as verbs, perhaps there should be adverbs that lift the verbs up into higher dimensions...
(comment deleted)
APL died for the same reason Perl is fading: it is a write-only language.

Those symbols look cool. But they're not very far away from Brainfuck.

Let's be fair. APL is write-only whereas e.g. Python is not, only in the same sense math notation in scientific papers is write-only whereas elementary school summation is not - the former is much more ergonomic once you have the prerequisite knowledge and experience, but most people only need the latter to conduct their business.
If a programming language can be written it can be read, but readability refers to enjoyment. Everyone has a hobby, but I don't think the masses would ever find reading Brainfuck enjoyable even if they were experts who coded in it every day. Whereas there are languages that are geared towards readability, with talented developers working in those languages, when combined are able to produce something that is something you would be glad to sit down and read; up there with the best novels of our time.
Therefore my comparison with mathematical notation. It can be used to write beautiful things, but the reader needs to have some knowledge to understand it and appreciate its beauty. Most importantly though, the density/opaqueness of the notation is what allows it to lift powerful ideas - to express in few lines what would otherwise take many pages.

It's not brevity for brevity's sake - it's understanding the limits of human working memory. The more verbose a description gets, the harder it is to work with it, until at some point, you just can't process it at all (at this point people start making indexes or developing notation to... make things more concise).

Comparing APL with Brainfuck is just ridiculous. The former is designed to be dense to enable efficient work; the latter is a joke that's designed to be sparse.

> Comparing APL with Brainfuck is just ridiculous.

What ever do you mean? The comparison in the first comment (which I did not write) is apt. They both use a notation of symbols that are derived from Western notation. There was no further comparison with Brainfuck made.

In that comment, APL was further compared with Perl, which perhaps is what you meant to write? Perl's 'write-only' nature largely stems from its ingrained use of regular expressions. There are, indeed, some parallels between regular expressions and APL, both utilizing some kind of notation to concisely describe function.

On that note, regular expressions were the first programming language I ever learned and I feel I have a good handle on them. I still find no joy in reading them. It's simply not a good language to read, even if it can benefit on the write side. I'm not convinced that knowledge and experience makes something more enjoyable. There are a lot of things in life that I have plenty of knowledge and experience in that doesn't translate to enjoyment.

APL is extremely high level but terse. Brainfuck is extremely low level with a very limited alphabet of input tokens. The two bear really no similarities.

People who decry Perl as a "write-only language" have very rarely given Perl more than a cursory look. It has a lot of syntax, yes. It uses some shorthand symbols, yes, but not to the extent that APL does. The complaints about Perl from C or Python fans are just the same complaints Lisp folks have about C or Python syntax. Most of them are quick to proclaim how superior Python is. Oh, but Perl doesn't have invisible syntax nor a global interpreter lock.

I wrote Perl for a couple of years early on in my software career. It's mostly write-only. Oh it can be used to write readable and maintainable code, but often isn't.
The typical Perl program is half as long as it should be to be readable and maintainable.
Is this an indictment of the language or the developer doing clever, terse quackery?
Mostly the latter.

In the rare occasions when I wrote Perl, the language offered all I needed to make my script as boring as Java, along with many temptations to be clever and concise; many people use Perl because it supports write-only "quackery", but it's their choice.

In Perl's case, it's both. Perl encourages it, and "perl practitioners" as a rule tend to revel in it (in my experience).
Cars can be driven safely, but often aren't.

Alcohol can be consumed in moderation, but often isn't.

Parents can raise kids without being emotionally and physically abusive, but often don't.

Marriages can be healthy and stable lifelong commitments, but often aren't.

Education can help raise people out of poverty, but often doesn't.

Governments can provide stability and security for their constituents, but often don't.

Makes me think we need a new language BNW (brave new world) where all the bad things people are doing in existing languages are simply impossible.
Poor analogies: none of what you describe is often the case out of deliberate action. Perl is often written deliberately in a way that is unreadable or maintainable. On purpose. Often because that’s what the language encourages.
Perl had the same problem as C++ and before that Ada have. There’s just too many ways to do things, so everyone use their own subset of the language and their own idioms. Which means that it’s hard for someone else to understand what you have done.
This particular criticism is fair enough. Before Ada there was PL/1, too.
But regular expressions, one of the culprits of Perl unreadability, have not faded, and are very much alive in all languages, and usually in ways that make them even less readable than in Perl (e.g. requiring backslashes to be escaped, or without support for verbose formatting).

Sometimes we all just put up with the unreadable mess when it solves the problem at hand quickly.

And, of course, for Perl-fans, Dyalog APL supports the full-fat PCRE, too :)
(comment deleted)
I disagree. The terseness of APL is the worst part about it. Its arcane symbols are a close second.

I don't want my programming language to be as terse as possible. I want it to be easy to read and maintain. I don't see how APL is a step in the right direction at all, and IMO should just be relegated to the dustbin of history as a failed experiment.

APL could serve the niche as a write only language. Not for code to be maintained, but for one offs. Of course, those one offs inevitably become code to be maintained, so maybe this niche doesn’t really exist.
It would also be a phenomenal spreadsheet language. the terseness means we get more visible code per cell block, the default data types mesh well, and the numerical orientation of the language is ideal.
We already have regex for unmaintainable, read-only code.
regex isn't a programming language, it is a language for describing strings that can be recognized by finite automata.
APL (and probably many languages in the Iversonian family) are more geared towards expressiveness, although terseness plays a large part of the language design.

Also, once you understand the rules of these languages when parsing expressions (which is always right-to-left unless the case of a parenthesis) and all the symbols, readability become less of a problem.

As for maintainability, well, it kinda depends on you and whoever is going to maintain it.

I do agree that the arcane symbols of APL is a minus, though. Which is why languages like J, K and Q are born: to make APL ASCII-friendly.

Generally speaking, this seems to me like a comment from someone who doesn't give APL more than a cursory look. And if that relates to you, please, try APL, or any other languages in the family, just even once. You _may_ change your view about it.

> Also, once you understand the rules of these languages when parsing expressions (which is always right-to-left unless the case of a parenthesis) and all the symbols, readability become less of a problem.

This is a very limited view about readability. Of course, once you get used to anything, it is more readable. But if most programming languages have moved away from symbols other than the standard ones precisely because symbols are a readability problem (even some languages like Python have and/or/not instead of &&/||/!, and those are pretty standard). It's easier to read "mod(1, 3)" than "1 % 3".

> As for maintainability, well, it kinda depends on you and whoever is going to maintain it.

Again, putting these issues on the people is missing the point of the discussion. Does the language incentivize the creation of easily understandable, fixable functions? Is it easy to detect and fix bugs? For example, assembly is harder to maintain than Python because a bug in assembly is hard to find, possibly complicated to fix because coding in assembly isn't really that easy... on the other hand, a bug in Python probably shows up as an exception even, that tells you in which line of code it's crashing.

> Generally speaking, this seems to me like a comment from someone who doesn't give APL more than a cursory look. And if that relates to you, please, try APL, or any other languages in the family, just even once. You _may_ change your view about it.

Honestly, J/K/Q/APL make it really hard to give them more than a cursory look. And the problem is that I've never seen a really good argument to do more than that. For example, first time I saw Haskell, it was hard to pick up, but at least I saw value in the proposition of immutability, pure functions, etc. Not for all use cases, but at least for some. I haven't given Go more than a cursory look but, again, the idea of a compiled language with GC and memory safety looks cool. I've never seen the value proposition of these family of languages other than "people who like them say they like them", and by the looks of the comments I don't seem to be the only one.

> because symbols are a readability problem

I think the difficulty of this is overstated. My kids are learning to read Armenian and English at the same time. 38 Armenian letters + 26 English ones, each with upper and lowercase versions. If a 6 year old can do it, you can learn a couple of new glyphs when programming.

> Honestly, J/K/Q/APL make it really hard to give them more than a cursory look. And the problem is that I've never seen a really good argument to do more than that.

It's a little disingenuous to claim that something you've never tried to do is too hard and has no value.

> Does the language incentivize the creation of easily understandable, fixable functions?

Lol, that is literally the point of them.

I've been really enjoying https://www.arraycast.com/ in which enthusiasts from several different Iversonian Array languages talk about how array languages enable them to solve problems differently.

> I think the difficulty of this is overstated.

I have my degree in mathematics and I've used my fair share of symbols. It's been a consistent finding in articles, books, classes and peer conversations that symbols are not that optimal. Inventing new symbols, or overusing them is frowned upon because they don't really make things easier to understand and can sometimes be a cause of confusion.

> It's a little disingenuous to claim that something you've never tried to do is too hard and has no value.

I'm not saying "it has no value", I'm saying that I've never seen a good argument to actually invest time in them. As I explained, other languages have clear value propositions. In J/K/Q/APL , the value proposition tends to be a vague "I like it" from people who like it.

> Lol, that is literally the point of them

Yes, 2_&{&/x!/:2_!x}'!R is very understandable.

> I've been really enjoying https://www.arraycast.com/

Offtopic, but I really dislike how so many information out there is the inaccesible format that is "podcasts".

> Yes, 2_&{&/x!/:2_!x}'!R is very understandable.

Just as much so as սուրճ or コーヒー or קפה.

> Offtopic, but I really dislike how so many information out there is the inaccesible format that is "podcasts".

I can't think of a better format for what they are trying to do with the ArrayCast. It's not teaching people array programming, just a conversation between people who are proficient in it.

What do you think makes podcasts inaccessible? For example, I often recommend https://soundcloud.com/lambda-cast to developers looking to understand functional programming. The conversational approach works well because some of the panelists are being taught these concepts for the first time and they ask great questions. There are plenty of books and articles on the subject, but conversational audio is a wonderful supplement.

> Just as much so as սուրճ or コーヒー or קפה.

But far less than the equivalent code in, say, Python, or C, or any other language. That's the point.

> What do you think makes podcasts inaccessible?

Lack of visible, searchable structure and the requirement of audio (in those that don't have transcripts, which is a lot of them) to get the information.

All episodes of the Arraycast have both transcripts and extensive show notes for background information for those who may not be array programmers. The challenge of delivering knowledge via an audio format is real, but use of transcripts makes it much more accessible.
Indeed, this podcast seems to do a decent job. It was more an off topic remark about how inaccesible podcasts usually are for actually finding information.
2_&{&/x!/:2_!x}'!R is very understandable to someone who knows K. (Or at least, the idea is, do you know what dialect it uses? Where's the code from?)

The (roughly) equivalent python is filter(lambda x:all(x%i>0 for i in range(2,x)),range(2,R)) - is this really that much better? (yes if you know python, no if you know k)

> (Or at least, the idea is, do you know what dialect it uses? Where's the code from?)

From Wikipedia page of K programming language https://en.wikipedia.org/wiki/K_(programming_language)

> filter(lambda x:all(x%i>0 for i in range(2,x)),range(2,R)) - is this really that much better?

You don't need to know Python. Filter is probably doing a filter, "lambda x: ... " looks like a lambda function, for looks like a loop... I am 100% sure that, without any language knowledge, the Python version is far more easy to understand.

Ah, that code was added to the wiki page in 2006 apparently. A modern version is basically the same anyway.

I will (maybe) agree that the python is easier to understand without any language knowledge - but that does not mean the K is not understandable. If you know K, it is understandable, and knowing a language seems like a pretty low bar for understanding it.

I mean, by the same measure, spaghetti code is not spaghetti code if it makes sense in your head. But we all understand that there are certain qualities of code that make it “spaghetti” or not independently of your understanding of it. Similarly there are features of languages (such as terseness, use of symbols, dependency on context) that makes them harder to read
If you don’t know a language but are hoping to read it, for what purpose are you intending to read it? Is it a casual understanding? If you’re talking about maintaining the code it’s probably better to stipulate that people already know the language. If you want to maintain code in a language you don’t know, I’m not sure you’d be a great hire.
Unless you have perfect memory and perfect recall, it’s very possible you’ll forget what a certain symbol meant. Specially if you read the code at a time you’re not being specially bright (say, Friday noon after an stressful week). Much harder to forget what the word “filter” means. Also much easier to recognize words than symbols where differences might be small.
It's really unlikely (imo impossible) you'll forget what a symbol means in APL or K etc if you program in it reasonably often. There aren't many symbols, and most of them are used pretty frequently. If you do forget, there's plenty of resources to jog your memory though. The Dyalog RIDE has a language bar at the top, and hovering over a symbol gives a brief description with examples. https://janiczek.github.io/tryapl-elm/ replicates this if you want to see for yourself. I disagree that it's easier to recognise words than symbols if there are small differences, the symbols are distinctive anyway so that's not really a real problem.
> It's really unlikely (imo impossible) you'll forget what a symbol means in APL or K etc if you program in it reasonably often.

Well, of course, if you’re always practicing the same thing you’re unlikely to forget it. That’s not always the case, though.

> the symbols are distinctive anyway so that's not really a real problem.

Really? From that toolbar alone I’m seeing empty circle vs slightly smaller empty circle, a lot of symbols with/without a dash or umlaut, dot and comma… seems pretty easy to get a lot of those confused or misread.

It seems like it might be easy to confuse things, but from experience, it isn't.

I feel like in general, you're making a lot of (fairly reasonable) assumptions about what programming in an array language is like, but they aren't really the case (as lots of other people have tried to explain). Without really trying it out, I'm not sure how someone could convince you otherwise, so there's a bit of an impasse.

I think you should listen to what people are saying and have said in the past though (https://news.ycombinator.com/item?id=33640275, https://news.ycombinator.com/item?id=22524918) and trust that for some people who do learn array languages, they do find it useful + productive, and a lot of the things you've raised are not issues in practice.

I have listened and to me it always seems to come down to “you make reasonable points but it’s not a problem for me so it’s not a problem”.

And I think there’s a lot of implicit bias when people who like APL say it’s perfectly readable. Given how readability hits you in the face first thing when you see APL and how it’s not a widely used language, only the people enthusiastic about it and willing to overlook the readability issues will end up learning it. Of course they don’t find issues in practice, if they had issues with that they’d have probably abandoned the language quickly.

> and trust that for some people who do learn array languages, they do find it useful + productive, and a lot of the things you've raised are not issues in practice.

I’m not saying it isn’t useful or productive. That’s not the discussion. The point is that they’re languages that they’re hard to use and hard to read. I don’t see how it’s such a controversial point.

For example, I like LaTeX a lot. I’ve done quite a lot of things with it, it’s been very useful and I’ve been very productive with it. I have no problem reading that code. But the fact that I have no problems doesn’t mean there aren’t actual problems with LaTeX. LaTeX will always be hard to read and quite a bit messy no matter how used I get to it.

Yes - the first thing you notice when you see APL is 'this looks weird'. Most people then assume 'this is complicated, hard to read, and hard to use', and move on with their lives. Some people decide to learn it anyway, and quickly (within under a day) realise it is actually simple, readable, and easy to use!

It's not like some people are magically born with the ability to read APL (or anything else), and learning it isn't a matter of 'overlooking the readability issues', but rather realising the 'readability issues' are a false assumption. There's not 'bias', there's just experience.

That is why "they’re hard to use and hard to read" is 'controversial', because it is just not true.

> Some people decide to learn it anyway, and quickly (within under a day) realise it is actually simple, readable, and easy to use!

Do you think all people who decide to learn it anyway end up with the same conclusions?

> That is why "they’re hard to use and hard to read" is 'controversial', because it is just not true.

So things like symbols having different meanings depending on number of arguments, prefix notation making the arguments of functions/operators stand out less, making it reading right-to-left (which is different from what you usually read - that brings the fun question of whether APL is left-to-right in Arabic countries), or having to know extra symbols that aren't used in other contexts... All of those things are not real?

I come back to the LaTeX example because to me that's very similar. I get when you say "I don't find APL hard to read/understand/work with" because I feel the same with LaTeX (even though it's not as obscure and "alien-looking" as APL is). I write slides in LaTeX faster and better than what I could do with Powerpoint. But that doesn't deny that there are a lot of things in LaTeX that make things harder, even when those are part of the core and when removing them would mean removing good things about the language too.

I think all people who try to learn APL for more than about 5 minutes end up realising most of their assumptions were completely wrong. Maybe they don't reach exactly the same conclusions (a lot of people do), but they reach similar ones.

> So things like <APL things> are not real?

They are real, but they are not issues for anyone who has tried APL at all.

Advent of code is starting soon, I'd recommend that you pick an array language and give the first couple of problems a go in it - even if you don't like it, at least it would save you from making yet more uninformed comments next time an array language article is on HN (and save array language programmers worldwide the pain of reading them).

Um, yeah. Knowing a language generally involves putting time into learning and the benefit is not forgetting stuff. You seem to not want to own the fact that your entire impression is predicated on it being not practical for someone not interested in investing any time into it. But I’m not sure that the input from such people is ever valuable.
APL is pretty big on immutability and pure functions too. Arrays are immutable, period, and the link below has John Scholes talking about the advantages of declarative programming back in 2005. And, uh, yes, APL tells you where the error is when you get one. It's pretty obvious you've bounced off due to a surface-level dislike for the syntax and are guessing about any other features it may have.

https://www.dyalog.com/uploads/documents/Papers/declarative_...

> It's pretty obvious you've bounced off due to a surface-level dislike for the syntax and are guessing about any other features it may have.

I'm not saying APL doesn't have those features. I'm making examples of languages that have a clear value proposition. If APL is big on immutability and pure functions, then why use APL vs, say, Haskell or Clojure? Same with the "where is the error thing", I was explaining why maintenance isn't just a "depends on who maintains it" thing, in fact the example languages were assembly and Python, nothing to do with APL.

I've talked to plenty of people whose eyes light up when you tell them 5 + 1 2 3 just works in the language. What you're saying is that you didn't find APL's value proposition attractive, and this is a fact about you, not APL.
> I've talked to plenty of people whose eyes light up when you tell them 5 + 1 2 3 just works in the language.

This is literally "people who like it say they like it". It's like saying that the value proposition of Python is having list comprehension, when that's just syntactic sugar.

And no, it's not just me, you just have to take a look at the comments or even the OP. The only point being made is that it has very powerful array programming primitives, but those functions can be easily brought to other languages (and indeed a lot of them have those primitives).

> It's easier to read "mod(1, 3)" than "1 % 3".

Why is it? You're assuming that I know what "mod" means, what the parens and comma signify (and perhaps what the lack of space in mod( but the presense of space after the comma indicate). If I didn't know those thing, they aren't at all readable and there's no way to guess. Wouldn't it be "1 modulo 3" for readability? Look at beginners in various languages posting on the internet asking what the different parens, braces and brackets do and when to use them. And then you're assuming that I don't know %, which because it's so common in C-like languages, I do, but if I didn't the glyph looks like division.

NB. that mod() implies modulus and % is remainder, and "rem" is even worse because it looks like BASIC's "remark" comment word. https://stackoverflow.com/questions/13683563/whats-the-diffe...

It's easier to read "(AA|AB)([0-9A-F]{7,10})ZZ" than to write that regex in a flowchart of if/else branches and string and state manipulation. And easier to verify it's correct. Just because you can write unreadably hideously long regexes doesn't mean regexes should be shunned for unreadability, for a range of patterns they are usable, convenient and powerful.

> "I've never seen the value proposition of these family of languages other than "people who like them say they like them", and by the looks of the comments I don't seem to be the only one."

I'm not sure they have one in the large scale; I would like one as a rectangular-pattern-regex inside another language or shell because of the notation, and not in the sense that "you can do the same thing with numpy". I can write text search in Java, I'd rather use grep.

I say the same thing about Rust and am regularly told to shut up.
don't you. think you can become better at it after some practice? let's compare that with mathematics notation or whatever... APL has less symbols than java's String methods.
> arcane symbols

I have never been able to shake the impression that APL is a troll language, like INTERCAL or brainfuck, except that part of the 'joke' is to insist that there's no joke. APL makes me feel gaslit.

The thing is, APL was originally designed as programming notation. It was used by Kenneth E. Iverson to discuss programming problems on blackboards with his students for years before it had an actual implementation.

So it has much more in common with math notation as a result, which is why the focus is on expressing yourself tersely with symbols. Also: nobody has to worry about special keyboards with symbols when writing those symbols with chalk on a blackboard, right? So the medium shaped the mode of communication.

I wonder what it would be like to learn programming that way, without using a physical computer. Maybe it would actually be a lot more pleasant for working through programming problems together? Mathematicians seem to be doing just fine working out their problems together on the blackboard with their notation after all.

EDIT: Hah, just saw that elsewhere in the thread an actual mathematician laments the (ab)use of symbols in their field, so I guess I was wrong there. Well, in that case, maybe mathematicians and programmers (or at least language designers) should join forces and see if they can come up with a more ergonomic notation together. A new Bourbaki club, so to speak.

I spent a fair bit of time with APL back in the 80s on IBM 3090 mainframe and a 3278 APL terminal and I have to say that if you've got an "APL shaped problem" and some familiarity with the language, it's easy to read and not so hard to maintain. Learning curve is a bit steep, though...
(comment deleted)
Hmm, feel q looses APL and K's conciseness with the ability to express yourself within a few characters rather than whole words
Well, the article said "renaisance" not "copy"
KDB+, using Q, is heavily inspired by APL. Great to look smart, might make you productive, horrible for cooperation, maintenance nightmares, heavy technical debt.

I'll pass, but you do you.

I remember reading the manual for arthur whitney's shakti/k9 and seeing this normative claim:

> Learning k9 means code like {x@(!#x)+\!#y} is clear and actually prefered to something much longer and verbose.

https://estradajke.github.io/k9-simples/k9/index.html

All I could think of was Abelson/Sussman's evergreen quote from the preface of SICP:

> Programs are meant to be read by humans, and only incidentally for computers to execute.

Lots of respect for Arthur, KDB+ was transformative when it arrived but I think now we need to move beyond that. Will take one or two decades for banks to migrate though lol.
It's also a misunderstood product from the outside. Unfortunately banks had a tendency to pay a bunch of senior engineers to do a build out for 3 years and then turn it over to cheap nearshore consultants to operate for 10 years. The core of most big bank code you see was written before 2010.

Where I have seen bakeoffs and largely failed attempts to replace, the challenge is the number of vendor & open solutions you need to cobble together to replace all the use cases that KDB supports. Every year it was a slightly different combination that didn't really cover all the bases.

To replace KDB in many of these large use cases, you need - a fast columnar PB-scale database, an efficient on-disk store, a fast in-memory cache, SQL support plus with expressive query language additions for time series operations, an event bus, a stream processor, and a programming language to write more complex applications close to the data.

A lot of the newer cloud-centric offerings are more about massive parallelism/scale than about pure single thread/individual request-response performance.

This is great for the vast majority of CRUD apps with millions/billions of users.

It's even great for some financial "backtesting" type use cases where you can kick off large

It generally isn't sufficient for many of the real-time financial use cases of doing ad-hoc analytics on billions/day datasets with expected responses in ms.

The biggest complaints are its expensive, and the devs are expensive. On the other hand you usually don't need as much hardware or dev staff to support it.

Hi Steve. See my reply in above thread to Shin which calls out alot of the operational improvements we've made. Just an FYI, there's also been significant changes in how we price so it's now alot easier to start small, get started quickly and decrease the time to value with more mainstream skillsets. With the new product strategy we're seeing alot more buy side clients (hedge funds/asset managers) use kdb+/q for their workloads with KX Insights.
> a fast columnar PB-scale database, an efficient on-disk store, a fast in-memory cache, SQL support plus with expressive query language additions for time series operations

Sounds like ClickHouse. And we see kdb slowly start being replaced...

Hi Shin - KX employee here (the creators of q/kdb+). We launched a new product to take our time-series tech to new markets and usecases with high performance analytic needs. Over the past 2-3 years we've listened closely to the community and have made huge improvements to make kdb+ easier to develop with using options like ANSI-SQL/Python/Stream Processing DSL/microservices/Open API etc. The banks are adopting all of the new kit quickly and leverage the cloud native capabilities (like kubernetes operators/object storage) to help scale and take their deployments to new heights without deep technical kdb+ expertise. Thought it was worthwhile calling out the adoption and product strategy here at KX.. lots more to come!

https://code.kx.com/insights/

Hey there thanks for your answer, know about this product, think you need to do better :-) Best of luck!
I think you might prefer notation y = a * x^2 + b * x + c to notation where those things are described some other ways. Same here, APL languages ask you to learn some notation - and then effectively use it, so the programs with that could be "meant to be read by humans".
If APL actually followed mathematical notation it would be extremely verbose. Most math books, articles and explanations use quite a lot of words, far more than symbols, precisely to allow them to be “read by humans”. Those are mostly used for computations and symbolic manipulations.
Nobody holds you from adding as much comments to APL code as you wish. I once wanted to write a parser generator in J, a very incomplete version is here - https://code.jsoftware.com/wiki/User:Alex_Mikhailov/Parsing . This is practically text, as you'd expect from a math article, with embedded code which allows computer execution to have those ideas working.
But there is a difference between “verbose code” and “adding comments”, isn’t it? There’s always the issue with comment-code disagreement. But mainly the point is about the language itself and the prioritization of terseness over unambiguity and intuition. Good mathematical notation strives for the latter, not the former.
> There’s always the issue with comment-code disagreement.

You just mentioned mathematical articles where the math expressions are a minority of the text, right?

> But mainly the point is about the language itself and the prioritization of terseness over unambiguity and intuition.

Math notation had - and keeps having - reason to be terser than plain text. Same for APL - which started life as "Iverson notation".

> Good mathematical notation strives for the latter, not the former.

Don't you think APL is a pretty good mathematical notation? If not, why?

No, I don’t think APL is a good mathematical notation. For starters, symbols having different meanings depending on whether they are dyadic or monadic is fairly confusing. That’s made worse by the lack of clear delimitations of arguments of functions. The use of prefix notation is also a bad choice because it doesn’t match the way we talk about a lot of operators. Symbols are overused even more than in mathematics (for example, why use a symbol instead of “log”?). There’s also a lot of symbols that are very similar, differing in small ways even though their meaning is fairly different.

Yes, mathematical notation is terse (mostly to make manipulations and computations easier to type) but people take special care to avoid ambiguity or too much context dependency, and also don’t try to introduce symbols for everything.

Exactly. If you cannot treat programmers as widgets to be swapped in and out why bother? Functionality schmuctionality.
APL + Lisp = O_o

https://github.com/phantomics/april/ and yes it is used in production©!

> What pushed the development of April really is that April is used by a hardware startup called Bloxl (of which I am the CTO). There are other users but Bloxl is the flagship application.

https://www.arraycast.com/episodes/episode23-andrew-sengul

Bloxl in use: https://user-images.githubusercontent.com/3721004/159686845-... See also the ELS conference 2022.

There was a paper in 1993 about "APROL: a Hybrid Language" that combines an array processing language and a dialect of Lisp (Scheme) in a consistent and useful manner. Seems like April is much further ahead!
I particularly liked this principle from the article: "learning all the alien symbols is a one-time investment, and expressiveness — the leverage you as a programmer gain — is for life."
Allow me to disagree. The page presents toy examples, and those are already unreadable. APL lacks data structures, modules, exception/error handling and typing. Well, since almost everything is a matrix of floats, perhaps typing isn't needed, but that idiom just deteriorates readability. You might think of it as a "bc" on steroids, but a rebirth for APL is uncalled for.
Multi-dimensional arrays provide all sorts of data structures, but modern APLs have also have namespaces/dictionaries, classes with inheritance, etc. Oh, and APL has had exception/error handling since the ’60s, with today’s APLs having rather flexible systems for this.
APL is from an era where impressively functional code that looks like line noise (another obsolete concept) was considered heroic. Other examples of such code are text editing and text formatting macro languages. Recall that EMACS stands for "Editor Macros" because that was its original implementation.

Back then, computers were so limited relative to human capability that this was still a good thing. Those days have gone. The bizarre syntax of APL has had its day. Its powerful array manipulation primitives can easily be brought forward into a language with modern syntax, and haven't they? In my company there is a lot of Matlab usage but I'm personally not knowledgeable.

> Its powerful array manipulation primitives can easily be brought forward into a language with modern syntax, and haven't they?

Kind of. The languages that one might expect to do this (Julia, R, NumPy) have picked out a few things from APL in an inconsistent way, leaving a lot as well. For example most are missing the generalization of prefix sum that APL calls "scan". So in [0], Conor was able to translate some code to every language in the APL family but not yet any outside of it. Another one, I don't think I've ever seen Replicate[1] outside the APL family. It's a generalization of filter to take an arbitrary count instead of 0 or 1 that's often useful if you know about it.

[0] https://github.com/codereport/array-language-comparisons/blo...

[1] https://mlochbaum.github.io/BQN/doc/replicate.html

I can't make head or tails of the first links, so I'll leave experts to it. The second one, yeah, it's nice syntaxical sugar, but it can be replicated very easily (map + "constant list" + concatenate). And versions of it exist in many languages - even C# has SelectMany https://learn.microsoft.com/en-us/dotnet/api/system.linq.enu...
All the good APL functions can be implemented easily (but please, they're just built-in functions, not syntactic sugar!). It's the selection of which functions to implement that makes it so much better for working with arrays.

"even C#" seems to imply you have less obscure examples than a function in a Linq package, is this the case? I admit I've never looked into Linq but I do see it come up in array language discussions sometimes. It's possible it has a more APL-like philosophy for a slightly different use case. The other difference is that APL uses a function on two arrays, which is nice because you can easily filter based on, say, the previous element.

EDIT: No, the C# function seems to only do the mapping and concatenation and doesn't even take a number of copies, that's really not the same.

Numpy has replicate (numpy.repeat).

Excel has SCAN.

Replicate looks like numpy's repeat. For example

  np.repeat(list("abcd"), [2,1,0,2])
is equivalent to the first example in the link.
Ah, thank you! I'd tried to find this for implementing BQN in NumPy (never finished) and didn't. Maybe I thought it only worked with a scalar for the number of repetitions.
Julia spells "scan" as "accumulate". I don't think we have something exactly like replicate out of the box, but it's a one-line function definition away:

     replicate(inds, v) = mapreduce(((i, n),) -> fill(v[i], n), vcat, enumerate(inds))
I agree with the spirit of your point though. Having operations like this as part of your 'alphabet' can be a really powerful thing. That's why I think APL is really well suited to being a domain specific language embedded in a language like julia. Shashi took a stab at this a few years ago, but it'd be nice to revive it: https://github.com/shashi/APL.jl
R has `rep` for replicate:

    rep(c("a", "b", "c", "d"), c(2, 1, 0, 2))
    c("a", "a", "b", "d", "d")
It was from an era of 110 baud teletypes. Thus, brevity was of extreme importance.
I had a problem in 2000-s when we needed to put some code into data files, and that code had to be short. So, when space was at premium, APL approach was rather convenient - even though it was already time of Skype and some video over the Internet.
Brevity is more important today.

The more thoughts you can fit on a page, the less taxing it is for your working memory.

We try to use abstraction - libraries, DSLs, even lowly functions - to tame ever more complex problems, but anyone who's had to debug a dependency of a dependency is painfully aware of the cost of leaky abstractions.

APL derivatives (like q) seem to have a niche use in the finance industry for processing time series data. I've played around with J (another APL derivative) and it was interesting. I could see it being useful for certain types of problems. Probably hard to use it on a large team though since it's so hard to read.

In R I often use the data.table library and the style of programming that encourages feels similar to how J made me think.

This dismissal doesn't address any of the points in favor of brevity and economy Iverson brings up in "Notation as a Tool of Thought".

> modern syntax

is mostly awful.

I'm not from this era and I love APL to bits. My brain is wired for extreme concision. Enterprise Java damaged my brain while APL and similar revives it.
Too much magic. I don't feel any fulfilment from knowing quirks of a specific language that not many others know. A waste of time IMHO.

Is it still pretty cool? Yes I think so.

> Even Haskell not only gained popularity on its own but deeply influenced F# and Scala.

The influences came from Standard ML and OCaml, primarly.

F# started its life as OCaml.NET.

Well, it won't happen. The language is too weird and for a language these days to make it, it has to target the lowest common denominator of developers.

Let's say you're at work, and you casually mention to your team something about APL, ATS or Agda. How many were excited about it? How many did roll their eyes? Yeah, I thought so.

(comment deleted)
Is the adoption of matrix oriented languages like Mathematica or Octave not the APL renaissance?
You can get everything there is in APL, plus no weird symbols in the J programming language.

> learning all the alien symbols is a one-time investment

No one time investment is needed if you want to learn J.

And yes, it does teach you to think in a new way. I am not kidding.

You can see the plethora of (mostly free) books available at the website [0].

Learning J has given me "enlightenment" at the same level The Little Schemer has given me.

(I don't recommend APL to anyone as you need to learn and painstakingly slowly insert those symbols. If you want to learn array thinking, go straight to J. Why waste time and headspace with APL symbols?)

[0]: https://code.jsoftware.com/wiki/Books

Well-chosen symbols aid thinking about the concepts. That's why mathematicians don't write their formulas in ASCII. Once you learn the keyboard layout, it is faster to type APL than J's two-glyphs and three-glyphs.
Ken Iverson invented J after he worked on APL and according to him J is an improvement upon APL.

Most people don't know about J, but know about APL because of those weird symbols.

I agree with your thoughts that not everything should be ASCII (and this is what many comments on this thread don't see), but don't reach the same conclusion as you do.

The core language of J was an improvement on the APL back then, but modern APLs have since borrowed many features from J. Iverson's choice of ASCII was because he wanted to make it more accessible to schools that couldn't get the equipment necessary to display APL glyphs. Note that J was released the year before Unicode.
The use of ASCII was a concession to the state of technology at the time. I don't think he actually preferred the ASCII digraphs to APL glyphs.
> a concession to the state of technology at the time.

Well, not anymore. But I will prefer ASCII over glyphs any day.

I have learned symbols in Math, and I keep learning newer ones.

It finally comes down to _RoI_.

The vast and tremendous return I get from non-ASCII characters in Math (and have gotten for decades)- I will not get the same amount from APL. It's as simple as that to me.

I tried to learn it multiple times, but something became very obvious to me when I used it in parallel to Q and read J for C progammers : J doesn't have a nice way to mimic keeping states between loops.

The J for C Progammers author divides loops in, I believe, 7 use cases and for that one he ends up using "an adverb" (a high order function) he wrote himself? Why? Because the language default adverbs don't support it.

In comparison, Q had very good support for that. Q also doesn't require learning symbols.

I haven't tried Q, and didn't read the book that you mention.

I learned J the same reason I learned Scheme- to expand my mind, and perspectives.

And I definitely would not want to use J for solving real-world problems, but I would definitely state that there are a lot of ideas in J-like languages that merit being looked into and being taken from there into modern Deep Learning frameworks.

And of course, it extends your mind.

> No one time investment is needed if you want to learn J.

I don't understand the "{J,K,Q} don't require you to learn new symbols" argument. You're learning a mapping between symbols and functionality, not literally learning to recognize the lines and curves that make up the glyph.

"reverse" is `|.` in J and `⌽` in APL. It doesn't seem obvious that the J mapping is easier just because I've seen those characters in other contexts.

It does take a little work to learn where they live on the keyboard, but that doesn't seem like a huge barrier to overcome. The live editor on the BQN site shows a list of glyphs and hovering shows you where they are on the keyboard. You just prefix with `\` to type them, so you don't even need any custom keymap.

This is great. I just wish the page fixed the GoL equation at the top of the page so I didn't need to keep scrolling back and forth.