4 min read

Hello and goodbye to the J language

I spent about 50 hours making things with a language called J. Its an APL progeny and it promises to make possible the expression of general programming tasks as if in mathematical notation. In J, arrays are first class citizens, and most functions natively support array operations. It also has fancy composition rules, so rather than the usual f(a,b), in J you have either f a or a f b. You read J from right to left and it has a few special rules about how operators combine during parsing which makes it possible to minimise the use of brackets and other superfluous notation. The J manual likes to describe the syntax in terms of verbs, adverbs, nouns and so on. A unit of execution is a sentence, and what you’re conceptually trying to do is compose sentences. Code in J ends up look a bit like this (k-medoid algorithm):

id=: 3 : '(y,y) $ ((y+1){.1)'
euc=: 4 : 0
row=. (+/@:*:@:-) & (|: y)
%: row "1 x
dist=: 4 : 0
d=. x euc y
^. d + id #d
scor=: 4 : '+/ <./ x{y'
step=: 4 : 0
's0 x'=. x
vec=. (i. <./) "1 |: x { y
argm=. 4 : '{ & x (i. <./) (+/ x { x {"1 y)'
p=. vec (argm&y)/. i. #vec
s=.(p scor y)
((s<s0) } s0,s);(s<s0) } x;p
vor=: 4 : '(step & y)^:_ (_;(x ? #y))'

The code is mine, and its pretty amateur but nonetheless there are no control statements, everything is super terse and it looks suitably like an ancient language; so all boxes ticked.

The power of J very much rests in its vocabularly of verbs mostly for array manipulation. Its a huge collection almost guaranteeing that however you solved the problem there’s probably a shorter and more elegant incantation. Vocabulary aside, the language itself is very lean. It has fancy parts but you can get a handle on the bread and butter (given that you’ve used functional languages before) in a matter of hours. If you get stuck the J community is legendary and will help you get your thing working often within an hour of posting to the forum.

All that is well and good but in the final analysis I’ve already said my farewells to J. There are awkward bits that one can live with: no named parameters to functions, overly basic namespace implementation, and so on. But the following were showstoppers for me:

  • A tiny package eco-system. If you have use cases in general programming or machine learning in no time at all you end up with requirements outside of J’s package eco-system, at which point you either have to use the FFI or write it yourself.

  • The foreign function interface (FFI) is great except that you end up having to juggle C types in J arrays which very quickly becomes absolutely horrible.

  • No parallelism. J doesn’t support parallel programming. No co-routines, threads, GPU support, etc. So if the problem is too gnarly for a single core, and you can’t do the parallelism at the OS level then you’re on your own.

  • Arrays and nothing but arrays. J doesn’t have basic data structures like hash tables, trees, tries, graphs, etc. If you’d like to use a tree for example then you have to figure out a way of representing it as an array.

An apostle of the J language, Dan Bron, writes on the jsoftware wiki: “One of J’s primary advantages is that it makes (array) programming easy. If its notation is inapplicable to your problem (more or less), there is not much reason left to use it.”. That aptly summarises how I feel about it too, except its not really about notation – I love the notation – its the vocabulary. J’s vocabulary is dominated by array processing verbs, and its not that it couldn’t have verbs for processing other structures, it just doesn’t. So one is left with the choice to either coax every problem in terms of arrays or use something else.