Introduction to J
Harvey Davies
CSIRO Division of Atmospheric Research,
Private Bag No. 1,
Mordialloc,
Vic 3195.
March 1994
J is an exciting new programming language designed by Ken Iverson, well-known
as the creator of 'APL'. He describes J as a dialect of APL, but the
differences from APL are more than sufficient to justify the new name.
Some important features of J are:
- Use of the standard ASCII character set rather than the special APL
character set
- It is array-oriented. Arrays are treated in a very systematic, general
manner. The elements of arrays can themselves be arrays.
- A rich set of verbs (functions) to manipulate nouns (arrays).
- Verbs can be modified, combined and defined using powerful facilities such
as 'adverbs' and 'conjunctions'. For example, the conjunction 'D.' gives
the derivative of a verb.
- Expressions are used to define verbs, adverbs and conjunctions, as well as
nouns. All four types of object are assigned names in the same way.
- Verbs can be defined in traditional 'explicit' manner using 'pronouns'
(variables representing nouns) to represent arguments.
- They can also be defined using a succinct 'tacit' (functional) programming
style which avoids the need to mention the arguments of the verb.
Iverson's company Iverson Software Inc. (ISI) has developed a J interpreter
and made it available as shareware. This interpreter is written in highly
portable C and runs on a wide variety of computers. These include the PC
(DOS, and Windows), Macintosh, Sun Sparc, Atari, Vax, Dec5500, Silicon
Graphics and various other Unix machines.
Although J can be used as a very sophisticated programming language, it can
also be used in a very simple way as a desk calculator. Thus if you type
'2+3', J displays the result '5'.
Expensive products like splus, matlab and mathematica may provide additional
facilities such as graphics and algebraic manipulation. However J is
unsurpassed for numerical calculation and manipulation of arrays.
ISI has published a number of books on J. The most useful is "J Introduction
and Dictionary", which costs US$30. There is an additional shipping charge of
US$10 within Canada/US and US$20 outside this area. There are discounts for
orders of at least ten. Diskettes are included free. ISI publishes a
newsletter which is free and includes a catalog of products. Orders can be
sent to: Iverson Software Inc., 33 Major Street, Toronto, Ontario, M5S 2K9,
Canada.
Source code and some documentation is available by anonymous ftp to
watserv1.waterloo.edu. Command 'cd languages/apl/j' provides a directory
containing various files including 'readme.doc', 'faq' (frequently asked
questions) and a compressed tar file containing the source code. It is
planned to include this introduction.
Another useful file in this directory is help/reference.card/reference.tex.
This can be used with tex to generate a two-page language reference summary.
Each row of table 1 lists the six verbs commencing with the graphic in the
first column. For example the "%" row indicates that "%y" means "1/y", "x%y"
means "x/y", "%.y" means "matrix inverse of y", "x%.y" means "matrix product
of x and matrix inverse of y", "%:y" means "square root of y" and "x%:y" means
"x'th root of y".
The Internet newsgroup comp.lang.apl includes a great deal of discussion
about J.
GETTING STARTED WITH J
The following annotated log demonstrates some of the basic facilities. Note
that command lines (which you type in) are indented while result lines are
not. Anything following "NB." is treated as comment.
You may like to run J while reading the following. This will enable you to
clarify points by experimenting. It is the best way of learning J.
I have followed Iverson in using grammatical terms in place of mathematical
terms. Thus 'noun' is used in place of 'operand' and 'verb' is used in place
of 'function' or 'operator'.
3 + 2 NB. Verb '+' adds nouns '3' and '2'
5
2-5 NB. Negative sign is '_' not '-'
_3
2e1 * _1.3 NB. '2e1' means '2*10^1'
_26
9 % 6 NB. Division symbol is '%' not '/'
1.5
2 ^ 4 NB. Power
16
radius=. 7 NB. 'radius' is pronoun. Assign is '=.' not '='.
radius NB. Display value (assign does not display)
7
2p1 * radius NB. '2p1' means '2*pi^1' (c.f. '2e1' above)
43.9823
7 3 _2 * _1 4 _9 NB. Arguments can be vectors
_7 12 18
radius =. 7 3 9.5 NB. Vector containing three radii
2p1 * radius NB. Three circumferences (scalar times vector)
43.9823 18.8496 59.6903
1p1 * radius^2 NB. Three areas
153.938 28.2743 283.529
-radius
_7 _3 _9.5
Most computer languages allow such a 'unary minus' i.e. '-' without a left
argument. Iverson has extended this concept to allow most verbs to take
either one or two arguments. Such verbs are said to be 'ambivalent'. The two
meanings are often related, but this is not always the case. A verb with a
single argument (e.g. '-radius' above) is said to have valence 1 and is
called a 'monadic verb' or 'monad'. A verb with two arguments (e.g. '2-5'
above) is said to have valence 2 and is called a 'dyadic verb' or 'dyad'.
The primitives (inbuilt verbs, etc.) are denoted by either:
- a single graphic (e.g. '%')
- a single graphic followed by '.' or ':' (e.g. '=.')
- a name followed by '.' (e.g. 'NB.')
The following demonstrates some common monads.
% 2 3 5 2r3 NB. Monadic '%' means 'reciprocal'. '2r3' means '2/3'
0.5 0.333333 0.2 1.5
^ 1 2 3 NB. Monadic '^' means 'exp'
2.71828 7.38906 20.0855
i. 9 NB. Monadic 'i.' generates integers
0 1 2 3 4 5 6 7 8
y =. _8 + 2 * i. 9 NB. and thus any arithmetic progression
y
_8 _6 _4 _2 0 2 4 6 8
* y NB. Monadic '*' is sign (signum) function
_1 _1 _1 _1 0 1 1 1 1
| y NB. Monadic '|' is magnitude (abs)
8 6 4 2 0 2 4 6 8
6 | y NB. Dyadic '|' is mod (remainder or residue)
4 0 2 4 0 2 4 0 2
New verbs (called 'pro-verbs') are defined by assignment, very much as
pronouns are defined. This can be used to assign familiar aliases, such as
'mod' in the following example.
mod=. |
3 mod y
4 0 2 4 0 2 4 0 2
%: 4 16 9 NB. Monadic '%:' means square root
2 4 3
%: _9 NB. '0j3' means '0 + 3*j' where j is square root of _1
0j3
3 %: 125 8 27 NB. Dyadic 'x %: y' means x'th root of y
5 2 3
!4 1.5 999 NB. Factorial. Monad always has argument on its right
24 1.32934 _
!y is generalised to non-integers by defining it as gamma(y+1). The third
element '_' means 'infinity', indicating overflow in this case.
We next consider how verbs are combined to form more complicated expressions.
The following expression contains three monads and represents '-exp(1/2)'.
-^%2
_1.64872
Note that the order of execution has to be right-to-left. It is treated as
-(^(% 2))
Most computer languages have complex rules for combining verbs. For example,
Fortran 77 has nine levels of operator precedence; most operators are
left-associative (executed left-to-right), one (**) is right-associative and
some (e.g. .EQ.) are non-associative.
Iverson's notation has no precedence rules. All verbs have equal rights!
There seems to be no good reason for having precedence rules. Such rules
would be horrendous in J which has about 200 primitive verbs and the capacity
to define any number of others.
The order is simply right-to-left for both dyads and monads. This may seem
strange at first, but it really is much simpler than the complex traditional
rules. There is much less need for parentheses.
9-5+2 NB. Treated as 9-(5+2)
2
3*4-2 NB. Simply right-to-left again
6
(3*4)-2 NB. Parentheses can be used
10
_2+3*4 NB. But can often be avoided
10
3+%4 NB. Combination of monad & dyad
3.25
y NB. Using y defined above
_8 _6 _4 _2 0 2 4 6 8
-3**y-2 NB. -( 3 * ( sign(y-2) ) )
3 3 3 3 3 0 _3 _3 _3
The dyadic verb 'o.' provides various trigonometric and hyperbolic functions.
Note the mnemonic association between the circular letter 'o' and functions
related to the circle.
1 o. 0.5p1 NB. '1 o. x' means 'sin x' so this is 'sin pi%2'
1
2 o. 60 % 180p_1 NB. '2 o. x' means 'cos x' so this is 'sin 60 deg'
0.5
It is convenient to assign conventional names (as pro-verbs) to these
functions. This can be done using the 'bond' conjuction '&' to define a monad
in terms of a dyad with one argument bonded (i.e. fixed or constant).
sin=. 1 & o. NB. sin is o. with left argument bound to 1
sin 360 30 90 % 180p_1 NB. sin of 360 30 90 degrees
0 0.5 1
The following comparison dyadic verbs return the result 1 for true and 0 for
false. Note that here ':' means 'equal'.
3 6 4 < 2 9 4 NB. less than
0 1 0
3 6 4 <: 2 9 4 NB. less than or equal to
0 1 1
3 6 4 = 2 9 4 NB. equal to
0 0 1
3 6 4 ~: 2 9 4 NB. not equal to
1 1 0
3 6 4 > 2 9 4 NB. greater than
1 0 0
3 6 4 >: 2 9 4 NB. greater than or equal to
1 0 1
As shown above, dyadic '=' does element-by-element comparison. There is also
a dyadic verb '-:' ('match') which tests whether the two entire arguments are
equal in all respects. The traditional symbol for 'congruent' comprises three
horizontal lines. So it is mnemonic to again consider the ':' to mean '='.
3 6 4 -: 2 9 4
0
3 6 4 -: 3 6 4
1
The dyadic verbs '<.' and '>.' give the minimum and maximum
3 6 4 <. 2 9 4 NB. lesser of (minimum)
2 6 4
3 6 4 >. 2 9 4 NB. greater of (maximum)
3 9 4
1 >. 8 <. 3 0 9 7 NB. restrict range to 1 to 8 (Again right-to-left!)
3 1 8 7
The advantage of treating true and false as numbers is shown in the following.
3 0 2 # 2 8 5 NB. 'x#y' means x copies of y
2 2 2 5 5
v =. 9 4 3 5 0
v >: 4
1 1 0 1 0
(v >: 4) # v NB. Select elements greater than or equal to 4
9 4 5
The logical operations 'and', 'or' and 'not' can be done as follows.
0 0 1 1 *. 0 1 0 1 NB. and
0 0 0 1
0 0 1 1 +. 0 1 0 1 NB. or
0 1 1 1
-. 0 1 NB. not
1 0
We have seen how J extends many verbs to arrays in an element by element
fashion. We now consider some other facilities such as adverbs. An adverb
has a single argument on its left. In the following, a verb to sum the
elements of a vector (or the columns of a matrix, etc.) is defined by '+/'.
The adverb '/' is called 'insert' because it has the effect of inserting its
verb argument '+' between each of the array items.
data=. 4 _1 5 2
+/ data NB. Monadic '+/' means 'sigma' i.e. sum
10
sum=. +/ NB. So let us define it as the pro-verb 'sum'
sum data
10
*/ data NB. Similarly, monadic '*/' means 'product'
_40
>./ data NB. and monadic '>./' means 'maximum'
5
-/ data NB. and monadic '-/' means 'alternating sum'
8
4 - _1 - 5 - 2 NB. In other words this (Remember right-to-left!)
8
# data NB. Monadic '#' means 'tally' or 'number of elements'
4
(sum data) % # data NB. So arithmetic mean is sum divided by tally
2.5
You may be surprised to learn that this can be written more succinctly as
(sum % #) data
2.5
sum % # data NB. which is quite different to this
0.25
sum ( % ( # data ) ) NB. which means this
0.25
% ( # data ) NB. or this (sum of a scalar is simply itself)
0.25
The original expression '(sum % #)' is evaluated first (because it is
parenthesised) to define a verb meaning 'arithmetic mean'. How can a sequence
(or 'train') of verbs define another verb? Here we have a train of three
verbs called a 'fork' and the resultant verb is used monadically. In this
case '(verb1 verb2 verb3) noun' is defined to mean
(verb1 noun) verb2 verb3 noun
Forks and other trains provide a powerful way of defining verbs. The following
definition of 'am' is a classic example of 'tacit definition'.
am=. sum % # NB. Define pro-verb 'am' as arithmetic mean
am data
2.5
max=. >./ NB. Similarly 'range' can be defined as 'max-min'
min=. <./
range=. max - min
range data
6
Note that such 'tacit' verb definitions do not involve noun arguments. We
could have used a more traditional 'explicit definition' of 'am' such as:
am=. '(sum y.) % # y.' : ''
am data
2.5
Note that in any explicit definition, 'y.' represents the right argument. The
':' separates the definition of monadic 'am' from that of dyadic 'am', which
is undefined in this case. We could define dyadic 'am' to give a weighted
mean as follows:
am=. '(sum y.) % # y.' : '(sum x. * y.) % sum x.' NB. 'x.' is left argument
1 2 0 3 am data NB. Weighted mean
1.33333
am 1 2 0 3 # data NB. Equivalent to this (using monadic 'am')
1.33333
ARRAY MANIPULATION
data NB. Display vector 'data' again
4 _1 5 2
0 { data NB. Dyadic '{' Extract element 0 from 'data'
4
2 1 { data NB. Extract elements 2 & 1 from 'data'
5 _1
data i. _1 2 NB. Dyadic 'i.' Find index of values _1 & 2 in 'data'
1 3
{. data NB. Monadic '{.' is 'head' i.e. 1st element
4
{: data NB. Monadic '{:' is 'tail' i.e. final element
2
}. data NB. Monadic '}.' is 'behead' i.e. all except head
_1 5 2
}: data NB. Monadic '}:' is 'curtail' i.e. all except tail
4 _1 5
2 {. data NB. Dyadic '{.' is 'take' i.e. take first 2 elements
4 _1
_3 {. data NB. If left argument -ve then take from end
_1 5 2
2 }. data NB. Dyadic '}.' is 'drop' i.e. drop first 2 elements
5 2
|. data NB. Monadic '|.' means 'reverse' (Mnemonic: '|' is axis)
2 5 _1 4
1 |. data NB. Dyadic '|.' means 'rotate'
_1 5 2 4
Specific array elements can be changed by using the adverb '}' ('amend') to
define a dyadic verb to change these elements. Say we want to change
element 1 to 0 and element 2 to 9.
v=. 1 2 } NB. Define verb 'v' to change elements 1 & 2
0 9 v data NB. Use it
4 0 9 2
0 9 (1 2 }) data NB. All in single expression
4 0 9 2
Note that this amendment process has three arguments. One is the argument of
the adverb and two are arguments of the resultant verb.
data, _7 0 NB. Dyadic ',' means 'append items'
4 _1 5 2 _7 0
mat=. 2 3$data,_7 0 NB. Dyadic '$' constructs an array with specified shape
mat
4 _1 5
2 _7 0
$mat NB. Monadic '$' gives shape (Mnemonic: $ like S = Shape)
2 3
$$mat NB. Shape of shape is 'rank' i.e. number of dimensions
2
+/mat NB. Column sums
6 _8 5
sum mat NB. since we defined 'sum=. +/' above
6 _8 5
sum"1 mat NB. Row sums. '"1' means over row vectors (i.e. rank 1)
8 _5
# mat NB. Number of rows
2
(+/ mat) % # mat NB. Column means
3 _4 2.5
am mat NB. Using above definition of 'am'
3 _4 2.5
am"1 mat NB. Row means
2.66667 _1.66667
0 { mat NB. Row 0
4 _1 5
2 { 0 { mat NB. Element 2 of row 0
5
|: mat NB. Transpose
4 2
_1 _7
5 0
We have seen above how the adverb '/' (or 'insert') defines monadic verbs such
as sum above. Such verbs also have a dyadic meaning.
2 3 4 */ 0 1 2 3 4 NB. Dyadic product (multiplication table)
0 2 4 6 8
0 3 6 9 12
0 4 8 12 16
Element (i,j) of the resultant matrix is defined by applying the verb ('*'
here) to element i of the left argument and element j of the right argument.
This is a convenient way of defining many matrices. For example:
i=. i. 5
i
i =/ i NB. Identity matrix
1 0 0 0 0
0 1 0 0 0
0 0 1 0 0
0 0 0 1 0
0 0 0 0 1
Dyadic 'x!y' gives the number of combinations of y things, x at a time.
|: i !/ i NB. Pascal's triangle (|: is 'transpose')
1 0 0 0 0
1 1 0 0 0
1 2 1 0 0
1 3 3 1 0
1 4 6 4 1
LINEAR ALGEBRA
Simultaneous linear equations can be solved using '%.', which is 'matrix
divide' as explained below. For example to solve the system:
3x - 6y = 10
9x + 15y = -14
A=. 2 2 $ 3 _6 9 15
A
3 _6
9 15
10 _14 %. A
0.666667 _1.33333
Thus the solution is x = 2/3 and y = -4/3. This can be checked using matrix
multiplication. Matrix multiplication is not a primitive, but it can easily
be defined using the conjunction '.' meaning 'dot product'.
matmul =. sum . * NB. Matrix product is dyadic sum of products
A matmul 2r3 _4r3 NB. Check result
10 _14
%. A NB. Matrix inverse
0.151515 0.0606061
_0.0909091 0.030303
(%. A) matmul 10 _14 NB. Matrix divide 'x %. y' is defined as (%. y) matmul x
0.666667 _1.33333
det =. -/ . * NB. Determinant is monadic alternating sum of products
det A
99
(3 * 15) - (_6 * 9) NB. In other words, this.
99