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