Skip to content

Technical Correspondence

Vector 18:4, page 129

language design

Transcribed from the printed issue; not yet reviewed. Read it in the PDF of the issue, page 129

Rank and Extending the Domains

Phil Chastney’s article on "Extending the Domains" (Vector Vol.18 No.3, pp.115-126) brings home with startling clarity the reasons why some of us have "defected" from APL to J. As Phil demonstrates, extending domains correctly in APL requires not only confidence in understanding a host of matters such as frame extensions, conformability, pervasiveness, splitting, joining, partially bound parameters and so on, but also presumes a knowledge of standards which arbitrarily adjudicate situations with plausible alternative interpretations, for example which should be the default axis. If I had known years ago that APL was this complicated I doubt if I would ever have touched it! By contrast, J domains are extended by correct application of the principles of noun rank and verb rank – that is all there is to say on the matter – my 16 words or Phil’s 12 pages, take your choice. Never did Occam have his razor so finely honed!

I accept that the concepts of verb and noun rank are initially quite subtle, but what wonderful benefits they bestow! I am sure that in writing interpreters Roger Hui must occasionally have had to tussle with matters of axis conformability, partially bound parameters and so on, but these are really matters of implementation, and removing the burden of them from users is something for which the rest of us are eternally grateful since it lets us get on with things which are really interesting, like programming and problem solving (or even play)!

Phil’s examples readily illustrate these points. First the J equivalent of 3 4⍴⍳12 is >:i.3 4 and is presumed to be assigned to t for convenience. J is often bracketed with other languages as an array language which I believe to be a misconception. J is first and foremost a list-processing language in which lists have the added feature of rank, a property which imposes uniformity on list lengths using fill items if necessary. For example, t above is not primarily a matrix but three lists of 4-lists in a rank 2 formation. <"1 t is also three lists of lists but with noun rank 1, which means that there is no requirement for the lengths of the lists to be equal.

Now introduce the shift verb, and importantly observe (from the Dictionary) that its left verb rank is 1, which means that in what Phil would call "the foundation model", a scalar left argument is applied to a vector right argument. Put into J parlance, the rank of the right argument must be at least one more than the length of the left, and if the right argument is a scalar, its rank is extended as necessary, so that there is no inconsistency in this limiting case. Thus 1 2 |.t means shift the lists themselves by 1 and items within each list by 2 so that the value of this expression is

 7  8 5  6
11 12 9 10
 3  4 1  2

1 0 2 |.t is a length error because it breaks the verb rank rule given above.

If I want to achieve Phil’s APL goal of 1 0 2⌽t then the appropriate action is to create a rank 1 list of lists as above and apply |. bound with open to each of them thus:

   1 0 2 |.&><"1 t

With lists of higher ranks, exactly the same principles operate with no additional rules about conformability, pervasiveness, extension or anything other such paraphernalia. Because verb ranks are made explicit in the Dictionary, semantics are unambiguously defined across objects of all noun ranks, and the task of delivering right answers is shouldered entirely by the combination of language designer and interpreter writer – or perhaps I should say Ken and Roger.

I could address each of Phil’s examples in the same way, but will restrict myself to one more example in which, incidentally, I think Phil mis-states the J interpretation.

   (u=.2 3 $'abcdef'),'XY'

is a command to append two 3-lists to a 2-list. The semantics of append require the result to be three lists, which must possess rank 2 because u has rank 2. This means that a fill item is applied to the list 'XY' to give a resulting list :

abc
def
XY

Phil discusses two other possible ways of "joining XY to u" – these are

abcXY  and  abcX
defXY       defy

In the first case the list 'XY' is appended to each of the lists on the left, that is appending is applied at verb rank 1, viz. u,"1 'XY'. An analogy in either language is 2 3+4.

The second case is analogous to 2 3+4 5, that is, there are two items on each side, rank 1 lists on the left and character scalars on the right, and so append is bonded with open in (<"1 u),&>'XY'.

Again all that is necessary is to apply the principles of noun and verb rank, no more than that. Perhaps it is worth noting that these ideas concerning rank were first observed in Sharp APL, so it is not too difficult to spot an evolutionary trail!