archives

J's concepts rank, composition, and GC

I've recently become interested in the J programming language - not so much as a tool I care to use but as a source of some interesting concepts.

I have found the recently revised "Learning J" by Roger Stokes to be extremely helpful for its economical and lucid presentation.

I have some vague questions to toss out to the world:

1) In J (as in APL), a multi-dimensional array is characterized by a list of dimensions called the array's "shape". For example, a tic-tac-toe board is of shape "3 3". The length of that list is called the array's "rank". Scalar (non-array) values have an empty list as their shape, and thus are of rank 0.

Simultaneously, J functions have a declared rank, which determines how array arguments are interpreted and where implicit iteration and reduction occurs. Borrowing an example from Stokes, the J function "*:" squares a number:

  *: 3
  => 9

That function is "rank 0" in its sole argument. If I hand it a rank 2 argument, there is an implicit map reduce:

   3 3 $ 1 2 3 4 5 6 7 8 9
   =>
     1 2 3
     4 5 6
     7 8 9


  *: (3 3 $ 1 2 3 4 5 6 7 8 9)
  =>
     1   4  9
     16 25 36
     49 64 81

My first question is Have any other languages besides APL and J made use of this concept of array and function rank as pertains to implicit iteration and reduction? (If you aren't familiar with and don't "get" how function rank plays out - it took me a while too - Stoke's book is helpful.)

Next:

In J, if I understand correctly, one may only define monadic or dyadic functions. Niladic functions are monadic but ignore their argument. Dyadic functions could theoretically be eliminated (because J has first class functions and every dyadic could be rewritten as a monadic function that returns a monadic function). It seems to be a stylistic choice -- a practical choice in the view of the designers -- to encourage people to think of factoring their programs into compositions of monadic and dyadic functions (and nothing more).

So the next question: Are there other languages of note that permit only monadic and dyadic function definitions? What impact does this have on the overall language design?

Next and finally:

J, as nearly as I can tell, makes an interesting compromise between being purely functional and being an imperative language with side effects.

Specifically (and glossing over I/O, for simplicity): only the bindings of explicit names in various namespaces are mutable. All values to which a name might be bound are themselves immutable.

One consequence of this is that, strictly speaking, fully general graph-tracing garbage collection is not needed in an implementation of J.

I'm aware of some other languages that share that property - such as AWK but I am wondering if there is any interesting theory out there or other careful thought that head-on analyzes the trade-off being made in mostly functional languages that forgo the need for graph tracing garbage collection by allowing mutation only of the bindings of named variables of infinite extent.