Amazingly, APL is more readable. Actually, it's even pretty intuitive. Which proves again, that restricting code to ASCII when every competent programmer (and PC-user in general) can enter almost any unicode symbols just fine is simply stupid.
You can enter any symbol but not quickly unless you set up some hotkeys or something. There is a key on the keyboard for e. Whatever you have to do for a unicode set symbol, it's going to be harder than hitting the e key.
And with regards to hotkeys, let's say you do Ctrl+alt+shift+esc+e to insert a unicode symbol, is that really better than just having a programming language where the common hotkeys are spelled out with a few ASCII characters?
And octothorp (#) is “eight-something”. Circumflex (^) is “bent around”. Names of most characters only sound academic because we don’t know Latin and Greek too good.
“√” isn’t even a natural character, it’s a graphical delineator between an index and a radicand, similar to ÷ or % forms of division. By “obelus” (sharpened stick) do you mean dot above and below a line, a percent, a dagger or just a line?
Sure there will be enough confusion with ~10-30 extra symbols that aren’t even on a keyboard and may not have a single meaning or a name.
APL predates Unicode! You used to have to use special APL keyboards to write it. The symbols were included in Unicode as a way to try and make APL more palatable.
There are esoteric code golf languages that use unicode. MPW (shell, assembler) used extended characters (MacRoman, not unicode but then again, APL also predates unicode) for some operations.
eg, instead of "echo yo >> file" you would "echo yo ≥ file"
Julia has support for Unicode operators. Most editor plugins for Julia allow you to enter the characters using (La)Tex syntax, so it’s quite common to see.
Unicode support doesn't really seem that uncommon, in the grand scheme. Rosetta Code's wiki has a page for languages that support Unicode variable names[0] and some of them were surprising to me (e.g. AppleScript).
Of course, supporting Unicode variable names doesn't mean a language supports Unicode anywhere, but it's a starting point for historical research at least.
I used to think that Lisp was bad, with its "God coded the universe in Lisp", then I read only the first part of your sentence, and was "Woha, so APL predates thought?!"
Haskell allows defining unicode operators, and has an extension that allows you to use unicode symbols instead of ascii sequences in various parts of the syntax.
In the Raku Programming Language there are several non-ASCII operators, although each of them has a pure ASCII equivalent. Some examples: ≤ vs <=, ≠ vs !=, ∈ vs (elem), etc.
I... just can't. I work a lot with data, so it sounds like it should be a good fit for what I do, but I find that writing the damn code in a normal language is much more productive. Maybe it's my brain that's wired wrong, but I fail to see how the entire construction is supposed to help.
A friend worked on a project in 2005 that had lots of K code in production. They had a contract with Kx Systems and Arthur Whitney in particular because, in my friend's opinion, only Whitney could really understand K code well enough to debug it. Friend's description was it took my friend two days just to comment the code into something grokkable by a normal developer, whereas AW didn't need to do that. Of course, it took Whitney those same two days of staring at the code before he said "Oh, of course, how silly of me." and found the bug and all resolved.
Part of those two days of commenting was that since K is interpreted all of the developers would hand-obfuscate all of the code so that the variables were a, b, c, etc. so that they would be slightly faster to parse than a multi-character string. This sort of thing is done all the time now, with JS to make it load faster, but his team at least didn't have any scripts to automatically turn developer-friendly code into interpreter-friendly code, they worked with the interpreter-friendly code version.
In my experience this practice isn’t obfuscation or for performance. The whole point of array processing languages is to amortize any fixed operation cost over the span of the array.
The notation-as-a-tool-of-thought camp prefers short identifiers on the principle that the more concise the expression, the easier it is to comprehend in total. This is not at all dissimilar from the general practices of mathematics.
Once you get used to it, it's just faster and stop noticing the 'oh line noise' thing. But like learning a natural language, you need to get to the point where you stop translating in your head and you think in the operators. Once you reach that, it is very hard to go back.
I think the main use for K and the other APL family languages is programmer lock-in. If you can get your employer to buy in and write the entire codebase in one of these languages, you can establish yourself as essentially irreplaceable and then demand large raises to retain you.
mine was matlab. thinking of everything as an array, especially things that aren't arrays, was the first pattern I ever learned. I've never used APL in anger but for the most part it comes very easily to me. Maybe not the code golfing and/or idiomatic APL style that people like to post but, like, using the primitives to create increasingly elaborate arrays before discarding anything I don't want, that part has always felt very straight forward.
Most of the time when you open a PL article on Wikipedia you're greeted with a Hello World example, but here you get this:
"""
[...] As a result, K expressions can be opaque and difficult to parse for humans. For example, in the following contrived expression the exclamation point ! refers to three distinct functions:
2!!7!4
Reading from right to left the first ! is modulo division that is performed on 7 and 4 resulting in 3. The next ! is enumeration and lists the integers less than 3, resulting in the list 0 1 2. The final ! is rotation where the list on the right is rotated two times to the left producing the final result of 2 0 1.
I think ‘used heavily’ is a bit of an overstatement.
I think the right intuition for APL-family languages is that they mostly do numpy-like operations except their set of operations tend to compose very nicely. So the idea is that one can quickly and interactively figure out a composition of the operations which will do the calculation you want, but you don’t have a complicated compiler and spend most of your time in the operators rather than the interpreted language, and the operators tend to make the cpu happy – they work on contiguous memory, tend to be vectorized, don’t branch unpredictably, etc – so even if you have to compose many steps, you win on the time to write and the time to execute can be hard to beat because the constant factors of each individual operation are good.
For obvious reasons, things like numpy, pandas, dplyr, etc are more popular as their syntax is a bit more readable and it is easier to get data in/out. I think they do lose a bit by not having lots of the useful compostable APL-style operators because those things don’t have comprehensible names.
Most of the operators are already familiar but they tend to work well on multidimensional arrays and with each other due to broadcast semantics (and some axis selection features). In other languages you may see the magic broadcasting for some operations like addition but many of the functions only work on vectors.
The actual thing that lines up a series of sell-at-this-price bids and the series of buy-at-this-price bids (or even more complicated types of orders, this the easy case) and crosses them over, figuring out who gets what bids filled by whom at what price, at supremely fast speeds and large volumes.
I did try looking it up fwiw. That was my guess but I was wondering if you meant something else and didn’t want to jump to conclusions.
I was surprised by the suggestion that kdb+ was used for this because a matching engine doesn’t really sound like the kind of case that APL-family languages would be well suited to – they tend to work well on large batches of data but for a matching engine, you have messages that come in over time and you want to process each message with reliable low latency (if you have higher latencies you will get wider spreads which is a competitive risk and leads to collecting less in fees), which means not operating on batches.
Do you have a source for the claim that kdb+ is used for the matching engine?
So the summary of that long post: we still need group but Shakti/k9 gets rid of it because it's too slow forcing the user to diy it with other primitives as needed?
I love it... It's the exact opposite of every other language design. Others: lets ship it with every tool a developer might ask for. K9: Occam's razor to everything. Nothing is safe.
there's a number of visionaries for lack of better term who have been following similar paths in their respective schools. chuck moore after FORTH got standardized went back to drawing board and made colorForth, where he reduced the number of available words to bare essential, very similar to how Arthur is rethinking and removing elements of apl in K, and then K in Shakti to what he sees as bare essentials. but you have less extreme cases, like Wirth developing pascal, then more capable modula, but then removing even arguable useful parts of modula in oberon, for being non-essential. I'm pretty sure there are other examples, but they like the examples I have given have small dedicated followings, rather than wide industry adoption, for reasons that wide industry adopted technologies tend to be all things for all people as a direct cause and effect of the wide adoption.
I think we need some kind of grouping function, but it doesn't have to be the 'generate group indices' function. I'm sure we'll have alternatives available such as `update ... by`.
MS has a 500+ person mailing list for peer help on kdb/q/whatever. They also have a site license, and herds of consultants from first derivatives.
It is much easier to become good at k/q if you have experts sitting next to you. Learning this at home (or reading about it on hn) can be very frustrating!
A group is a non-empty set and an operation that combines any two elements of the set to produce a third element of the set, in such a way that the operation is associative, an identity element exists and every element has an inverse. /s
Group is actually like inverse a mapping. Given an array A which map index to value, group A map value to index.
A common idiom is: desc count each group A , which list most frequent element first
From the way I often use Haskell, Matlab, and even crazy shell one-lines with lots of pipes, awk, sort, and other stuff, I often have the impression that array languages are exactly what I'm looking for for certain problems.
The question is... which array language should I pick? What are the reasons to pick one over the other?
I don't really like J but the only serious APL left is the proprietary (though free, and fun) Dyalog; K, the official product, is also proprietary and because Arthur rewrites it every couple of years all the open source clones are of different versions so there isn't much of an ecosystem.
it's libre and gratis, if that's not something that bothers you (and to be sure if you're just writing code for your own edification it's not a practical problem) then i would recommend dyalog, although as a side effect of being open J has a (perhaps only slightly) larger free ecosystem and community.
the down side is that subjectively some people (myself included) find J uglier, less effective as a tool of thought and due to some syntactic features (hooks and forks, but no proper lightweight anonymous function syntax)-prone to people posting impenetrably dense code as "examples"
Do you know if it's available from GNU/Linux repositories? One thing that bothers me with single letter language names is that it makes searching information cumbersome, due to lots of noise in search results.
I see, thanks! Looks like I might try both. The "no proper lightweight anonymous function syntax" sounds weird to me, I would have thought that's paramount for an array language? Do I misunderstand?
In J if you want to do something fairly complex without writing a function you can pile up a bunch of verbs/operators into a big (point free) verb-train. You can't do recursion, loops or explicit flow control but in the Array Languages that's not much of a handicap, it can get pretty hairy to read though
In dyalog you can (as of about v13) do that if you want, or you can just use curly brackets { and inside of them have lexically scoped variables, multiple expressions, recursion and if/then (no loops either though) }
is $ meaningful in verb trains? because that was what I was referring to when I said no loops/recursion/flowcontrol
N.B. a sibling says J has added a direct definition construct while I wasn't watching which renders my comment largely irrelevant although the I feel general point that a lot of J 'example code' tends towards difficult-for-noobs to parse verb trains still holds.
i love k. it's a much smaller and regular language than APL and some of its derivatives. you can look at John Earnest's oK. it's fantastically documented and a great learning resource.
i would also recommend BQN. it has an active community and it's designer Marshall Lochbaum explicitly tried to address some of the warts in APL and j. he's done a great job.
learning any of the array languages will be a tremendous learning experience if you haven't approached the paradigm before
I had a similar feeling, but ultimately found Haskell more maintainable. If you write it point-free with well chosen symbolic operators, it winds up being the best of both worlds.
Not that I have any firsthand experience with the matter, but I think Morgan Stanley has been switching over from K to some Haskell-like dialect as well.
In the Wordle dict example, it would have helped if a type system could tell me I was wrong when I assumed that an indexing miss would generate an empty list.
Yep - added a link to some simple examples in the article (below). Throughout the article there are also a few links to executable versions of the code examples.