A Critique of The Programming Language J

I’ve spent around a year now fiddling with and eventually doing real
those languages which produces a special enthusiasm from its users and
in this way it is similar to other unusual programming languages like
longer having access to a Matlab license, wanting an array oriented
free programming style, two aspects of programming which J emphasizes.

Sorry, Ken.

Sorry, Ken.

interfaces to gnuplot and hive and doing Bayesian inference and
friendly critique of the language.

First, The Good

particularly valuable property in a general purpose programming
involves interactive exploration of the structure of data and for that sort
chopping, slicing or reducing some big pile of data is pretty
terseness allows an agile sort of development style.

Much of this terseness is enabled by built in support for tacit
programming. What this means is that certain expressions in J are
mentioning values.

values selected from the rows of an array. In J:


J takes considerable experience to read, particularly in Tacit
find the max of each row and sum the results.

something which operates on data. We may capture that meaning:


Or use it directly:


denoting the average operation. The forkness is that it is three
expressions denoting verbs separated by spaces.


J has one other really nice trick up its sleeve called verb


NB. monadic and dyadic invocations of <
4 < 3 NB. evaluates to 0

do that by modifying the rank of -:

x -:”(1 1) y

use rank annotations to quickly describe how verbs operate on their
it can be executed quickly.

the really nice parts of the language.

The Bad and the Ugly

the syntax and semantics which make the language confusing without
offering additional power. These unusual design choices are
particularly apparent when J is compared to more modern programming

Fixed Verb Arities

procedures from other programming languages, have arity 1 or
which case context determines which function body is executed.

this strategy:

multiArgVerb =: monad define
‘arg1 arg2 arg3’ =. y
NB. do stuff

simple destructuring occurs. Boxed items are unboxed by this
operation, so we typically see invocations like:


parentheses) just denotes a boxed array.

entirely relates to how arguments are extracted from array valued
generalized to functions of arbitrary argument count.

the best separator is the space character.1

A second, related problem is that you can’t have a
zero argument function either. This isn’t the only language where

Consider the following definitions:

o1 =: 1&-
o2 =: -&1




Ok, so it produces a verb.

 3 3 $ ''

│     │o1          │o2          │

them really seem right, in my opinion.



That many of these combinations evaluate to o1 or o2 is doubly
confusing because it ignores a value AND because we can denote


function very well. Instead of having a single, unified abstraction
representing operations on things, it has a variety of different ideas
like Java 7 without first order functions, but ultimately this
handful of disparate techniques fails to acheive the conceptual unity
of first order functions with lexical scope.

Furthermore, I suggest that nothing whatsoever would be lost (except
J‘s interesting historical development) by collapsing these ideas
into the more typical idea of closure capturing functions.

Other Warts

Weird Block Syntax

Getting top-level2 semantics right is hard in any
language. Scheme is famously ambiguous on the subject, but at
J neither is the same.

We may write block strings in J like so:

blockString =: 0 : 0 
Everything in here is a block string.       

turned into a verb.

plus =: 3 : 0


plus =: 3 : 0
  plusHelper =. 3 : 0
  x plusHelper y

This forces to the programmer to do a lot of lambda lifting
manually, which also forces them to bump into the restrictions on
function arity and their poor interaction with rank behavior, for if



plus =: 3 : 0
    plusHelper =. +
    x plusHelper y   

they disappear as soon as execution leaves the conjunction or adverb

directly into the representation of a function. Essentially all modern
its most recent binding is.


folded all down into regular old functions without harming the
benefits of the language, and simplifying it enormously.

If you don’t believe that regular old first order functions with
tacit-programming libraries in R and Javascript. I
even wrote a complete, if ridiculously slow implementation of J‘s
rank feature, literate-style, here.


a boxed list. It is evaluated like this:



2 Top level? Top-level is the context where everything
which call the redefined function change their behavior, or do they
instances created before a change in the class definition. Believe or

On the opposite end of the spectrum are really static languages like
is only meaningful as a monolith, for the most part.

14 thoughts on “A Critique of The Programming Language J

  1. Ewart Shaw

    (1) Note that a verb is signalled by 3 : 0 , not 0 : 3 .
    (2) J really is best thought of as a language, so adverbs, conjunctions etc. are natural. Forks etc. can be read left-to right if you insert words like ‘of’ and ‘the’ appropriately. For example, mean=: +/ % # can be read as ‘mean is_defined_to_be sum_of divided_by number_of’.
    (3) Thank you for writing this friendly critique!

    1. Vincent Post author

      Thanks for the corrections – I’ve modified the post.

      On the subject of adverbs and conjunctions let me say a bit more for any inexperienced reader who might be looking at the comments.

      In J the world is divided into nouns, verbs, adverbs and conjunctions. Nouns are values, verbs modify values, adverbs modify verbs and conjunctions also modify verbs. The interpretation of the latter two is complicated somewhat by the fact that they can also modify nouns. It is actually easier to see adverbs and conjunctions in terms of their results: they are the semantic elements which can return a verb and have the result interpreted correctly in tacit and non-tacit expressions.

      NB. This is distinct from a gerund, which is a sort of quoted verb (to borrow Lisp nomenclature). That is, a gerund is a noun which some verbs, adverbs, etc know how to interpret as a verb.

      In the main body of this post I mentioned the issues of scope without elaborating much on its relationship to these ideas, but they are deeply interrelated. If you cut your teeth on functionalish languages like Scheme, like I did, then in J you will rapidly find yourself wanting to write functions which modify functions. J, as stated, provides for this urge via adverbs and conjunctions and even gerunds. But the more consistent solution to this problem is to just let verbs float up to the value domain along with nouns. Why? Because then the programmer need only learn the rules governing the semantics of one domain (admittedly, there needs to be some rules resolving variable bindings in verbs as well). While we may use natural language as a guide to understand expressions involving adverbs and conjunctions, the rules for the meanings of `u`,`v`, `m`,`n` in adverb and conjunction definitions can get hairy fast, particularly if you want to simulate noun or verb capture (either dynamically or lexically). Why not just let verbs be nouns and let verbs modify verbs? This is not how natural language works, but programming isn’t natural language.

      The elephant in the room here is that by restricting the value domain J is able to have a simple, efficient evaluation strategy without having to answer or even consider questions like “What are the semantics of a non-scalar verb?” But the interpreter is meandering into that territory anyway with things like gerunds, so why not go whole hog? I’m not an expert on the J interpreter, but my understanding is that its cleverness is primarily in avoiding allocation, but data analysis is not a soft-realtime job, generally, memory is cheap and plentiful and garbage collectors are good. Plus, performance-wise, J lags behind languages like Matlab and R, in my experience, so it might be better to entertain other evaluation strategies anyway.

  2. Martin

    Underneath this line
    “NB. monadic and dyadic invocations of <"
    the comparison's remark should read
    "4 < 3 NB. evaluates to 0"
    as (0) means 'False' in J.

    Has made a good read (I do always learn something from people with different perspectives).

    1. Vincent Post author

      So true – I’ve fixed the link, but here it is for any reader in the comments. Thanks for catching that! I believe I was writing this post on an airplane and meant to fill in links I couldn’t find without an internet connection.

  3. Danielle McLean

    “In an expression (x;y) the effect depends on whether x is boxed already or not. If x is boxed, then y is boxed and appended. If x is not boxed then x and y are boxed and appended.”

    Your description of ; is backwards – it actually always boxes x, and conditionally boxes y if it’s not already boxed. Try (<1);(<2);(<3) for example.

    1. Vincent Post author

      I’ve never had occasion to program in APL. My main concerns are the semantics of higher order functions and whether lexical closures work. If APL functions similarly to J, then similar critiques would probably apply.


Leave a Reply to Wilfred Hughes Cancel reply
