J for C Programmers
jsoftware.com
jsoftware.com
What I think I've got so far (this is all hearsay, and none should be taken as fact):
APL: The original. Non-ASCII. APLers hate the successors, because "notation is tool for thought" and ASCII is a poor representation. Main implementations GNU APL (slowish), Dyalog (fast and expensive, free version available, good documentation)
K: ASCII, used in finance (among other sibling languages, dependent on the concrete company and concrete group within a company), comes with kdb+ (columnar data store, integrated with K), very fast (main interpreter loop in processor cache), one real implementation (very very expensive, limited free version available), several cvariations on the language, some of them open source, none comparable
Q: syntax sugar upon K, but otherwise exactly the same
J: another evolutionary strang of APL, impeccable pedigree (Iverson), free software, experiments more with language features, is more complete when it comes to the "linguistic" style (adverbs etc.), database available (Jd, but this database is commercial), slower than K, more extensions like for GUI programming
May also be worth nothing that k4 is essentially "undocumented" and Kx encourage to use q instead of writing any code in k directly. Most functionality can be pieced together using docs from other versions of k (I think k2 manual is floating around online) & the docs from q.
edit: k5, k6, k8 were apparently never released (https://aplwiki.com/wiki/K)
k5 was also known as "kOS" and was to be a version of k as a full OS that could run directly on hardware - I believe that got abandoned due to the pain of writing drivers
http://archive.vector.org.uk/art10501320 - article about kOS before it was abandoned
The major difference separating j from k is that the former is optimized for multidimensional arrays (_i.e_ math), while the latter is optimized for vector processing (_i.e_ financial data) and uses lists of vectors when working with higher dimensions.
J is also fast, but not for the same things as k. It's interpreter is also designed to fit in the cache.
Dyalog APL has been experimenting with bytecode compilation, although I don't know whether it's implemented in the current version. It also has a gpgpu extension with restrictions on the language (Co-dfns). Unlike j, APL does not implement operations such as matrix multiplication by calling to BLAS, so if you're doing matrices on the CPU, use J. As an aside, j also shines for graphical output with its opengl bindings and its 2d/3d Matrix viewer.
BTW Jd is indeed commercial, but is free to use in non-commercial applications.
Personally, I think that k is much more popular on hn because they're aggressively promoting it. J is better if you're not doing financial work.
$ du -sh /usr/lib/j9/bin/libj.so
3.2M /usr/lib/j9/bin/libj.so
Might be a tight fit...Kdb k is only 771kb, and shakti k is 120kb.
Speed relative to K, for example, is largely dependent upon what operators are used, with what size and shape of data. Certain operations in J are highly optimized, comparable to C (or exceeding) what you'd find in matrix math libraries.
Many of those choices have been added to Dyalog APL since then, SQUAD indexing function, trains, rank adjustment operator.
Dyalog APL has traditional APL functions and keywords which looks a lot more procedural than the golfed symbols mostly shown - for loops, if statements, etc. which GNU APL has not, IIRC; and has an object system :Class and a bridge to the .Net framework and C# interop both ways, GUI support possible through that (Windows Forms I think).
I'm perplexed by this one. I'll concede that the APL symbols are prettier but why does it magically stop being a notation just because you use combinations of ASCII symbols. Especially when many APL symbols are composed of units themselves.
⍲ vs *: One is 'notation' because it has the two units stacked on top of each other and the other is not because they are stacked horizontally?
So I simply assume there is something deeper going on than "it looks ugly". Maybe someone here is in that camp and can tell us. At least the argument was made on HN in some earlier APL or J thread.
Notation is obviously a shorthand for "sensible notation" or even "better notation" there, because obviously just about anything can be notation. Including laying out pebbles on a beach.
But further than that, I don't know.
Some people hold prejudice against parentheses and prefix notation, for others it's ASCII...
J uses . and : as modifiers to a base operator to create a pretty big set of primitives. See https://code.jsoftware.com/wiki/NuVoc
I mean, in a fixed-width font (as people tend to use for programming) it's literally twice as long. That adds up.
This is less true since APL has begun integrating J semantics and operators, but still..
Iverson solved some remaining inconsistencies in J, and it includes some elegant concepts as tacit programming (+/ % # for the arithmetic average is beautiful) that were not in the original APL, but I do not see myself writing J in the whiteboard or a notebook.
But ASCII may not be the main problem. Curiously, I find that K performs much better in my whiteboard test than J, perhaps because the set of symbols is much smaller. And if you think it may be a matter of getting used to it, I have worked with APL far less than with J and still find the APL symbols more appealing.
There are many things I like about J, and I do not have a very rational explanation to give you, but I agree with those that say that APL is a better tool of thought.
In ordinary text, we separate words with spaces, and add punctuation at the end of sentences to further make the structure apparent. (Well, now we do...a lot of pre-modern writing would justwritethewordssmushedtogetherlikethis [1]). In most of the sample programs in APL successors I've seen there usually didn't seem to be space between symbols.
[1] https://www.bbc.com/culture/article/20150902-the-mysterious-...
Re: one-or-two characters, there are a few exceptions, like the folds ( F.. F.: etc.) which are new to J9. Also some older ones like {:: (Map) and &.: (Under) where `x u&.:v y` means `v^:_1 (v x) u v y`. Some of these aren't verbs but conjunctions, adverbs, etc. For the most part they stick to one or two. There are parsing rules that dictate what the second and third characters can be (that's why you see so many colons and periods), and these rules are actually discussed in the JforC book.
Reading J can be tough, as a fellow learner I feel your pain. :) The one that usually gets me (in my own code, even!) is
5 myverb \ n
...which runs the verb over 5-element slices of 'n' at a time, and joins up the results. The '5' is too far away from the '\', and it can be hard to see the connection right away. I understand why it's so (it's really running the modified verb 'myverb\' with arguments 5 and n) but I still find it hard to read.When writing my own code, I often leave extra spaces between the multi-character words, and anywhere else that helps legibility. J might be a terse language, but there's no point being crazy about it (unless you're golfing).
https://en.m.wikipedia.org/wiki/Variable-length_code#Uniquel...
This is debatable. Given the clause in Kdb+ on demand license [0], it is healthy to give all the published performance figures the benefit of doubt.
[0] "1.3 Kdb+ On Demand Software Performance. End User shall not distribute or otherwise make available to any third party any report regarding the performance of the Kdb+ On Demand Software, Kdb+ On Demand Software benchmarks or any information from such a report unless End User receives the express, prior written consent of Kx to disseminate such report or information." -- https://ondemand.kx.com
there are also other use cases for C. since it is close to the metal, it is a good fit for security-sensitive, heavily-audited codebases, because there are fewer layers of abstraction to audit and a smaller attack surface. manual memory management makes it a good fit for performance-sensitive applications, real-time encoding, signal processing, etc., because a garbage collector isn't competing for CPU time.
there's a lot of overlap between all these use-cases, though, and most of it comes down to the fact that C:
* is compiled,
* has manual memory management,
* is a relatively small language with a relatively small standard library,
* (and of course, we can't ignore the network effect) is ubiquitous.
so, when i see a document to introduce me to a new language, and it claims to be written for C developers, the first thing i am going to look for is some information about the language so that i can judge whether it is even remotely suitable for the contexts in which i would normally write in C.
i read "foreword", "introduction", "culture shock", and "running a j program", looking to answer some questions like: is it compiled or interpreted? if interpreted, how complex is the interpreter? if compiled, does the compiler use LLVM or some other intermediate AST? is it garbage collected? can the garbage collector be turned off? how does performance compare?
the only passage that tried to answer "why should i bother?" is a couple of sentences in the foreword:
> To begin with, for the productivity. J programs are usually a fifth to a tenth as long as corresponding C programs, and along with that economy of expression comes coding speed. Next, for the programming environment: J is an interpreted language, so your programs will never crash, you can modify code while it's running, you don't have to deal with makefiles and linking, and you can test your code simply by entering it at the keyboard and seeing what it does.
all of that is true of python too, but that doesn't mean python can do what i do with C.
When you see a book titled "Japanese for English speakers", what it means is that it builds on your knowledge of English to teach you Japanese, not that its goal is that you replace your usage of English with Japanese. Certainly, the book will not include a justification of how you can use Japanese to speak in London and New York as you can do with English, and probably it won't even bother explaining you why learning Japanese may be a good idea. And, yes, you probably could learn Chinese instead, but that is not the point.
C is a language that has a reason for existing. However C exposes programs to categories of errors that are not even possible to represent in other languages. In my opinion security code should be as error proof as possible, and C is definitely not a good language to accomplish that goal in. (I used to be a professional C programmer)
it's not the only option, maybe there are even some better options these days from a purely technical standpoint, but C is used in heavily-audited security-sensitive applications despite its syntactical/design shortcomings because it keeps you close to the metal.
Any language compiling into native code has this advantage.
You perhaps meant that in C the programmer actually codes closely to how it's going to look like in native code. That could be an advantage; but for that C brings disadvantages, which come from one actually having to code like this - there is no other way.
The question what's more important - language constructs which are closer to actual hardware or language abstractions which prevent certain bugs from appearing - isn't that clear.
This book is quite suitable as a first book on the subject. It's a good reference, too, for basic mechanics; for style in organizing longer thoughts one would go besides the book.
There easily could be a few "aha" moments while reading. One could be in the discussion on verb ranks - then the words at the beginning, about the general commanding the army as a whole, becomes clearer. Another is a classification of loops - an unusual viewpoint for traditional C approach.
These languages (APL, J, K) promote a programming paradigm that sits somewhere in between the continuous spectrum between imperative and functional paradigms.
There is lot of good to absorb from J, and not little of it has fortunately permeated into the famous Python's numpy library. Many people have been inadvertently using APL/J deepest concepts thanks to it.
I do think that, even if they are beautiful, they are still generations away from a community Zeitgeist that would render as widely spread as, for example, Haskell.
The triple quotes are ugly.
Quit bellyaching...
I love it. So many arguments in PLT are really just about not ever wanting to leave ones comfort zone. Sometimes you just have to suck it up and do a thing.I like that it doesn't evangelize and it doesn't disparage C, it just explains the logic behind the differences.
The more I think about what we do in Software the more I value readability. I think one of the reasons I love D is that it clearly treats readability as a design requirement.
I just wish there were more jobs out there using Dlang...
But you can't use the standard library if so, right? Or rather you can use some parts of the standard library but not others, and some third-party libraries but not others? It was never clearly explained what does and doesn't require GC.
> and is working on a borrow checker type system like in Rust.
But it only started work on that after Rust became established. So why wouldn't I just use Rust, which has a borrow checker I can use today?
I used d for quite a while, and I still think it's much better than c++. However, it's ultimately just more of the same: an incoherent, tangled mess. Slightly more coherent, slightly less tangled, sure. It's possible to iterate on garbage, but you still wouldn't want to serve it at a restaurant. Worse, it has politics. Prominent d users regularly talk about forking the language/compiler; not because of any specific language pain points, but because of pathological problems with the way the language is developed.
The main compiled/native language to watch imo is cone[1], though most of its ideas are not yet implemented. Zig is also decent, and closer to production-ready.
I did enjoy fumbling around in ike [1], a javascript-based K playground :-)
"J for⍤0 0⊢ C Programmers" ≢ J for C programmers.
"J for⍤1 0⊢ C Programmers" ≢ J++ for C programmers.
"J for⍤0 1⊢ C Programmers" ≢ J for C++ programmers.
"J for⍤1 2⊢ C Programmers" ≢ J++ for C# programmers.
"J for⍤2 2⊢ C Programmers" ≢ J# for C# programmers.
etc. Then with `commute` ⍨ we can swap the argument order as well: "J for⍨⍤1 0⊢ C Programmers" ≢ C++ for J programmers.
etc.(Assuming C has a single implicit plus, C++ is a 1D array of plusses, C# has a 2D matrix of plusses)
I'm looking for some inspiration. (I think) I'd love to use one "for real"/"in anger" for something but are they too niche to use as CV/Resume enhancement?
What's good about Matlab? Maybe the best comparison I've seen in a normal language would be LINQ in C#. If you've been writing (or reading) code that makes heavy use of LINQ, imagine re-implementing all that stuff using explicit loops with dummy indices and all the rest of that line noise. Yuck. Hard to write and worst of all hard to read.
Matlab takes that further than LINQ does ... in certain directions. Basically stuff with arrays.
I don't know whether the APL-likes take the same idea even further than Matlab, or just use short keywords.
Downside: when your problem doesn't break down into array patterns that Matlab is good at, then Matlab stops being fun. At all. For stuff like that, where you really do need to supervise every line of C-ish code personally, something like Ruby or C# is way more fun. (Except if you're doing say EE or optical physics. Then Matlab's libraries are still a huge time saver.)
It was alright. I don't think I was able to invest enough in APL to make it really stick but have the impression that if I did it could be very useful.
Fwiw, Aaron Hsu is really the guy to follow for all things APL. He's also super nice and helpful and a model for anyone who wishes to represent a technology.
There's utility in knowing it in the same sense as knowing Lisp; makes you better at other languages. There's also social capital in that people who use and work on the APL family are a sort of "mafia" working on very interesting and lucrative problems (generally in quant finance).
I've been surprised at how much I liked writing it. J can be derided for being a "puzzle language"[1], which isn't entirely unfair, but I've found the paradigm of array programming carries over into more widely used languages and libraries ("Iverson ghost"[2]).
I wouldn't bother learning to put it on a resume, I would try it out for fun.
[0]: https://idle.nprescott.com/2020/ray-tracing-in-j.html
[1]: https://prog21.dadgum.com/219.html
[2]: https://analyzethedatanotthedrivel.org/2018/03/31/numpy-anot...
Sometimes, when the logic of a program is clear, J could be like a calculator for quickly getting a result. Actually, with J you're pretty soon at a point where you're refining the specification, not actually solving the problem (because solving is easy). There is a saying that an hour-long task APLer solves in 5 minutes and then spends the remaining 55 minutes refining the solution - and the problem - so they'd be clearer.
At some point J feels easier than other tools and it does feel like a "tool for thought" - a shorter way between what you think and what the program does. There can be even shorter ways, I don't know.