The preferred way to learn J seems to be via a series of half-truths and tutorials. I hate learning like that. I want The Truth. (Since I originally wrote that I’ve discovered the cryptic documentation for J. Life is good.)
The basic types in J are the number and the array. There are other types too, like character, and I suspect more that I don’t know about. I expect verbs and adverbs (functions and higher-order functions) will turn out to be members of some type. Values are called nouns.
The array appears more fundamental in the sense that every other noun exists as an element in some array (I think). Like Lisp an array has N dimensions or axes. The number of axes, N, is called the rank. N >= 0.
An array of rank 0 contains one value. An array of rank 0 is called an atom or scalar. Compare this to #0A7 in Lisp (bet that has you looking up reader syntax).
Each axis has a non-negative length and is indexed using a 0-based index.
Arrays of rank 1 are called vectors and also lists. They have a convenient literal syntax:
1 2 3 NB. vector of length 3
Aside: comments are introduced with «NB.»; this is kind of cool and kind of perverse.
Computation is performed by applying verbs to nouns. Various verbs have a literal syntax; verbs can also be produced from adverbs. A given name, such as $, can stand for a monadic verb (1-ary) or dyadic verb (2-ary) according to how it is used. Syntax for monadic application is
verb noun, for dyadic application is
noun verb noun. Adverbs come after the verb:
verb adverb. Evaluation and grouping is generally right to left. So
2 * 3 + 4 evaluates to 14 (dyadic * and + have the conventional meaning).
In the following example my typing is indented, the results printed out by J are exdented. This is conventional for J.
$ 1 2 3 3 # 1 2 3 3 $ 9 NB. Result is a 0-length vector. Which prints as a blank line:
Note the last result. $ applied to the scalar 9 (an array of rank 0) yields a vector of length 0.
Applying # to the result of $ will give us the rank:
# $ 1 2 3 1 # $ 9 0
Dyadic $ can be used to construct arrays of arbitary shape (left argument) filled in with some value (right argument):
2 3 $ 1 1 1 1 1 1 1 2 0 3 $ 9 NB. an axis is 0, hence 0 elements # $ 2 0 3 $ 9 3
Note that the second array in this example has a zero-sized axis. It contains no values but still retains its shape. This is very similar to the situation in Lisp: (array-dimensions (make-array ‘(2 0 3))) ⇒ (2 0 3).
Strings have a literal syntax, ‘foo’, and are vectors. Except—hack!—a literal string with just one character is a scalar:
'foo' foo $'foo' 3 $'' 0 $'f' NB. Recall a scalar's shape is a 0-length vector.
Dyadic $ can take a vector on the right (and arrays of higher rank, but something slightly hairy happens then):
2 3 4 $ 'foo' foof oofo ofoo foof oofo ofoo
Observe how ‘foo’ is used to fill in the array, how the rank 3 array is displayed, and how the elements are ordered lexicographically by index (row major, but that gets slightly confusing above rank 2).
The adverb / is what we know and love as foldr (if only every higher order function had its own domain name). / turns a dyadic verb into a monadic verb that folds the dyadic verb along a list (“inserts into” according the J crowd). It can be used to yield the number of atoms in an array:
2 * 3 6 */ 2 3 6 */ 2 3 4 24 */ $ 2 2 5 $ 'foo' NB. same as */ ($ (2 2 5 $ 'foo')) 20 */ $ 7 1
Note the last example, the scalar’s shape ($ 7) is a 0-length vector which when * is folded over it yields 1. 1 is the identity for *. Recall that in Lisp (*) ⇒ 1 for similar reasons.
There’s plenty more to learn about arrays, and that’ll come in part II.
PS. If J intrigues then see how I learnt to multiply in colour using it.