Leroy J. Dickey
University of Waterloo
This article is intended to be an introduction to the language J and some of its features. J is a high powered general purpose programming language. This dialect of APL uses the ASCII character set, has boxed arrays, complex numbers, the rank operator, and some novel compositions of functions.
Like APL, J is an array language. Any time one wants to do calculations with more than one number at a time, or with more than one name in a list, a collective (an array) is the right structure to use, and J is designed to do such calculations easily.
Those who write programs for themselves and who want their answers quickly will be happy with the swift and concise way programs can be written in J.
This article consists of several examples that illustrate some of the power of the language J. Each example presents input and output from an interactive J session, and a few lines of explanation have been added. Lines that are indented with four spaces are those that were typed in to the J interpreter, and the lines that are indented with only one space are the responses from J. Other text lines are comments that have been added later. The topics that have been chosen for inclusion do not come close to telling everything about J, but some of them represent subjects that at one time or another the author found new and exciting.
J is a general purpose computing language, and is well suited to a broad spectrum of programming needs. Because the interests of the author are in mathematics, examples are primarily mathematical in nature.
In this discussion about J, the words noun and verb are used to stand
for data and functions, respectively. Thus the four letter character
In the assignment
This example shows how calculations are done with a list of numbers and
how J uses a functional notation. That is, each verb (function) acts on
the noun or pronoun (data) to its right. It is easy to create a
collective (array). Here, for instance, are 9 integers:
i. 9 0 1 2 3 4 5 6 7 8 a =. i. 9 a 0 1 2 3 4 5 6 7 8
! a 1 1 2 6 24 120 720 5040 40320
% ! a 1 1 0.5 0.166667 0.0416667 0.00833333 0.00138889 0.000198413 2.48016e_5
+/ % ! a 2.71828
+/ % ! aas "the sum of the reciprocals of the factorials of a".
Those who have done some programming in almost any other language, will see that the expression
+/%!i.9is a remarkably short one for a function that produces the sum of the first few terms of the series that approximates e. Moreover, it is possible to pronounce this program in English in a way that precisely conveys its meaning, and those who know the meaning of the words in the sentence will be able to understand it. And anybody who knows the mathematics and who has learned this much J will recognize that the program does exactly what the English words say and that it will produce an approximation to e.
The author finds this expression in J much easier to think about and understand than the corresponding program intended to compute the same number in certain older languages. Here, for example, is what one might write in Fortran, to accomplish the same result:
REAL SUM, FACT SUM = 1.0 FACT = 1.0 DO 10 N = 1, 8 FACT = FACT * N SUM = SUM + 1.0 / FACT 10 CONTINUE PRINT, SUM STOP ENDCompare this Fortran program with the J program that uses only a few key strokes:
+/ % ! i. 9. Not only is the J program shorter, but if you agree with the author that the program more closely approximates the English description, then you will probably agree that the J expression is easier to understand, even for someone who may have been using some other programming language, and who has only just learned the meaning of the symbols used in this example. The use of this compact notation brings about much shorter programs. It is the author's experience that for some applications, the ratio of the number of lines of Fortran or C code to the number of lines of J code has been about 20 to 1.
In this example, two proverbs (defined functions) are given. As before, lines indented with four spaces were given as input during a J session, and the ones immediately after, with one leading space, were produced by the J interpreter.
Sum =. +/ Average =. Sum % # c =. 1 2 3 4 Average c 2.5The first two lines create proverbs, the third creates a pronoun, and the fourth invokes the proverb (function) Average with the pronoun (data) c. The meaning of
Average cis this:
(+/ % #) 1 2 3 4and this may be thought of as:
x (f g h) y means (x f y) g (x h y) .This diagram may help you to understand the meaning:
g / \ f h / \ / \ | | | | x y x yand the figure might suggest to you why the name fork is used. In a similar way, used with one argument,
(f g h) y means ( f y) g ( h y).Thus, looking again at Average c, we can see that this has the same meaning as (Sum c) % (tally c).
If the above definition of fork strikes the reader as awkward, the reader is invited to consider a thought experiment about the meaning of the English phrase "a is less than or equal to b". Imagine that there is a function LT which returns the value 1 when a < b and 0 otherwise. Imagine a function EQ which returns the value 1 when a=b, and 0 otherwise. Imagine and a function called OR so that the expression x OR y returns 1 when x is 1 or y is 1. Then the meaning of the fork (LT OR EQ) is understood by noting the equivalence of the statements:
x (LT OR EQ) yand
(x LT y) OR (x EQ y).
pr =. +%The next two input lines show a use of this hook. From them you should be able to see that the meaning of "a pr b" is "a plus the reciprocal of b", that is 5 +% 4 :
5 pr 4 5.25And this next example means 4 + % 5 :
4 pr 5 4.2The function pr is defined above as +% , and the expression 4 +% 5 is equivalent to 4 + (% 5). This diagram for 4 +% 5 may help to understand its meaning.
+ / \ 4 % | 5Because of the shape of the diagram, the combination of two verbs in this way is called a hook. In general, x (F G) y means
x F (G y) .To continue with our example,
1 pr 1 pr 1 1.5The above input line may be read as "1 plus the reciprocal of (1 plus the reciprocal of 1)". And here below is an analogous line with four ones:
1 pr 1 pr 1 pr 1 1.66667 1 pr (1 pr (1 pr 1)) 1.66667 pr / 1 1 1 1 1.66667 pr / 4 $ 1 1.66667The above input line has exactly the same meaning as the three input lines that come before it. Notice that the value of the result is the same in each case. The / is an adverb called insert and the result of pr/ is a new verb, whose meaning is derived from the verb pr.
In traditional mathematical notation the above expressions are all written
1 1 + ------------------------ 1 1 + ------------------ 1 1 + ------------ 1This particular fraction fraction is the first part of a famous continued fraction because it is known to converge to the golden ratio. That means that if you just keep on going, with more and more ones, the value gets closer and closer to the golden ratio. One can see that the values of the continued fraction expansion seem to converge by using \, the prefix adverb. It creates a sequence of partial results. Here is a nice, compact expression that shows the values for the first 15 partial continued fractions.
pr /\ 15$ 1 1 2 1.5 1.66667 1.6 1.625 1.61538 1.61905 1.61765 1.61818 1.61798 1.61806 1.61803 1.61804 1.61803In this, you can see that the numbers seem to be getting closer and closer to some limit, probably between 1.61803 and 1.61804. If you concentrate only on the odd numbered terms, (the first, the third, the fifth, and so on), you will see a sequence of numbers that is monotonically increasing. On the other hand, the even numbered terms, ( 2, 1.66667, 1.625, and so on), form a sequence of numbers that is monotonically decreasing. Of course these observations do not constitute a proof of convergence, but they might convince you that a proof can be found, and in the light of these observations, the proof probably follows along these lines.
Can you think of a simpler way to represent and evaluate continued fractions? This author can not!
The golden ratio has been known for thousands of years, and is the number, bigger than one, such that itself minus 1 is its own reciprocal. The golden ratio is usually denoted by the lower case Greek letter tau. It is said that pictures whose sides are in the ratio 1 to tau or tau to 1 are the most pleasing to the eye.
a =. 100 200 b =. 10 20 30 c =. 1 2 3 4This is the beginning of the data construction: two numbers for a, three numbers for b, and four numbers for c. Again, we use the verb Sum, a modification of the verb plus, defined as before:
Sum =. +/But in this example, the usage is different, because we use it with a right and a left argument. To get an idea about the action of the verb Sum used dyadically (that is, used with two arguments), notice what Sum does with just b and c:
b Sum c 11 12 13 14 21 22 23 24 31 32 33 34Now we are ready to see and understand the next step. Here the collective Beta is built, using a, b, and c.
Beta =. a Sum b Sum c Beta 111 112 113 114 121 122 123 124 131 132 133 134 211 212 213 214 221 222 223 224 231 232 233 234This rank three array may be thought of as having has two planes, each having three rows and four columns. The function $ (shape of) tells us the size of the array.
$ Beta 2 3 4Now examine what
Sumdoes with the data:
Sum Beta 322 324 326 328 342 344 346 348 362 364 366 368Can you see what is happening? It is adding up corresponding elements in the two planes. Twelve different sums are performed, and the result is an array that is 3 by 4. The action happens over the first dimension of the array.
But we might wish to add up numbers in rows. We can do it this way:
Sum "1 Beta 450 490 530 850 890 930And to add up numbers in each column:
Sum "2 Beta 363 366 369 372 663 666 669 672The expressions "1 and "2 are read as 'rank 1' and 'rank 2'. The rank 1 objects of Beta are the rows, the rank 2 objects are the planes, and the rank 3 object is the whole object itself. So, when one asks for Sum"2 Beta , one asks for the action (Sum) to happen over the rank two arrays, and the action happens over the first dimension of these arrays.
Finally, the expression Sum"3 Beta has the same meaning as Sum Beta .
Now, recall the definition of Average.
Average =. Sum % #Apply the proverb Average to the pronoun Beta, to get:
Average Beta 161 162 163 164 171 172 173 174 181 182 183 184The result is the average of corresponding numbers in the two planes. That is, the average is calculated over the objects along the first dimension of Beta. If we would like to know the average of the numbers in the rows, we type:
Average "1 Beta 112.5 122.5 132.5 212.5 222.5 232.5and finally, averaging the columns of the two planes:
Average "2 Beta 121 122 123 124 221 222 223 224Again, compare the sizes of these results with the sizes of the results above where we were asking simply about sums. The verb $ (shape of) will help us here:
Sum "1 Beta 450 490 530 850 890 930 $ Sum "1 Beta 2 3 $ Average "1 Beta 2 3 $ Sum "2 Beta 2 4 $ Average "2 Beta 2 4What the author finds exciting about this example is not just how easily the nouns and verbs were built, but how every verb acts in a uniform and predictable way on the data. Rank one action is the same kind of action whether one is summing, averaging, or whatever. It has been said that the concept of rank is one of the top ten computer inventions of all time. [Monardo, 1991]
... i also believe that the rank operator is a wonderful invention, up there in the top ten computer inventions of all time.
This quotation appeared in an article in the UseNet news group comp.lang.apl, by Pat Monardo of Cold Spring Harbor Laboratory, Message-id: <1991May17.firstname.lastname@example.org>.
http://www.watserv1.uwaterloo.ca/languages/jand is available from certain other servers. At the Waterloo site, versions of J are available that run on several kinds of computers. J is a product of Iverson Software Inc., 33 Major Street, Toronto, Ontario, Canada M5S 2K9. 1 + 416-925-6096, and when purchased from them, comes with a dictionary of J and other aids for learning J.
The reader who chooses to learn J from the tutorials might like to print the 47 tutorial files and study them one at a time, and to have at hand a copy of a status file listing the names of the verbs. For each example given in the tutorial, the reader might wish to experiment with J by inventing nouns, verbs, adverbs, and conjunctions to test ideas related to those presented in the tutorial and thereby to let J itself be the guide and the interpreter (pun intended).