Help / JforC / More Verbs
>> << Pri JfC LJ Phr Dic Voc !: Rel NuVoc wd Help J for C Programmers
8. More Verbs
Before we can write more complex programs, we need to learn some more verbs. We will group them into classes and give a few mnemonic hints.
Before we start, I should point out a convention of J: if a dyadic verb is asymmetric, for mnemonic purposes you should think of x as operating on y. One way to express this is to say that x is control information and y is data. Another way is to say that if you were applying the verb many times, you would expect to apply the same x to different ys rather than the other way around. We will note the exceptions to this rule--%, /:, \:, -, -., and e.--and the reasons for the exception.
Arithmetic Dyads
All these verbs have rank 0 and produce a scalar result, so if they are applied to two operands of equal shape the result will also have that shape; if applied to two operands that agree, the result has the shape of the larger operand.
x + y addition
x - y subtraction (y operates on x to match the mathematical definition)
x * y multiplication
x % y division Note that the slash has another use, so % is division. You don't have to worry about division by zero: it produces _ (infinity) or __ (negative infinity) except for 0%0, which yields 0 .
x ^ y exponentiation (x to the power y). 0^0 yields 1 .
x ^. y logarithm (base-x logarithm of y)
x | y modulus (remainder when y is divided by x . For the longest time I had trouble remembering dyad |; it seemed that the divisor should be y by analogy to dyad % . The inconsistency is that J defines x % y as 'x divided by y' to match accepted practice in mathematics; that makes dyad % anomalous in J, because we have y operating on x).
The comparison verbs have rank 0, and produce Boolean results in which 1 means true, 0 means false. They use tolerant comparison, which means that two values that are very close to equal are considered equal. This saves you the trouble of adding small amounts to mask the effects of floating-point rounding: 1 = 3 * 1 % 3 is 1, unlike 1.0 == 3.0 * 1.0 / 3.0 whose value depends on the compiler. If you need exact comparison, append !.0 to the verb. Look under 'Comparison Tolerance' for details.
x = y equal
x ~: y not equal (if you squint the colon looks like an equal sign)
x > y greater-than
x < y less-than
x >: y greater-than or equal (if you squint the colon looks like an equal sign)
x <: y less-than or equal
Boolean Dyads
These verbs have rank 0 and are applied to Boolean arguments to produce Boolean results:
x *. y Boolean AND
x +. y Boolean OR
x = y Boolean XNOR (1 if the operands are equal)
x ~: y Boolean XOR (1 if operands differ)
Min and Max Dyads
These verbs are useful for performing tests, because they perform the operation item-by-item, replacing a C loop that does a test for each atom. They have rank 0 and produce a scalar in each cell, so the result has the shape of the larger operand.
x >. y the greater of x and y
x <. y the lesser of x and y
Arithmetic Monads
These verbs have rank 0.
>: y increment (y+1)
<: y decrement (y-1)
<. y the largest integer not greater than y (floor function)
>. y the smallest integer not less than y (ceiling function)
| y absolute value of y
* y signum of y (_1 if y is negative, 0 if y is tolerantly close to 0, 1 if y is positive). Tolerantly close to 0 for * means differing from 0 by no more than the comparison tolerance, which is slightly different from the rule for > and < .
.-. y 1-y
Trigonometric Functions
x o. y creates the entire family of trigonometric functions of y . Think of dyad o. as a monad, selecting the function based on x . For example, 1 o. y is sin(y), and _3 o. y is arctan(y). Except as noted below, (-x) o. is the inverse of x o. . For mnemonic purposes, note that the odd numbers specify odd functions.
x o. y |
x |
(-x) o. y |
Comments |
sqrt(1 - y*y) (same as |
0 |
|
Self-inverse |
sin(y) |
1 |
arcsin(y) |
|
cos(y) |
2 |
arccos(y) |
|
tan(y) |
3 |
arctan(y) |
|
sqrt(1 + y*y) (same as |
4 |
sqrt((y*y) - 1) (same as |
|
sinh(y) |
5 |
arcsinh(y) |
|
cosh(y) |
6 |
arccosh(y) |
|
tanh(y) |
7 |
arctanh(y) |
|
sqrt(-(1 + y*y)) |
8 |
- sqrt(-(1 + y*y)) |
Not inverse |
Real part of y (same as {.@+. y) |
9 |
y |
Not inverse |
Magnitude of y (same as | y) |
10 |
Conjugate of y (same as + y) |
Not inverse |
Imaginary part of y (same as {:@+. y) |
11 |
iy |
Not inverse |
Angle of y (same as {:@*. y) |
12 |
eiy |
Not inverse |
Boolean Monad
-. y (rank 0) Negate y This is simply the boolean interpretation of 1-y .
Operations on Arrays
These verbs operate on entire arrays; the data operand (usually y) has infinite rank (in other words, the verb operates on the entire data operand), and the control operand has whatever rank is appropriate for the operation performed. I am going to give a highly simplified definition of the functions of these verbs; consult the Dictionary to see all they can do.
Dyads
Selection: { # -.
x { y (From)
No, nothing was left out! { is not paired with }; it is a verb and stands by itself.
The left rank is 0; the result is item number x of y . One of the great insights of J is the realization that selection, which in most other languages requires a special syntax like C's y[x], is really just a dyadic verb like any other. Examples:
2 { 3 1 4 1 5 9 4
y has rank 1; its items have rank 0; item number 2 is 4 .
2 4 { 3 1 4 1 5 9 4 5
The left frame is 2; each atom of x selects an item of y (each an atom), and the results are made into a 2-item list.
1 { i. 3 3 3 4 5
y has rank 2; its items have rank 1; item number 1 is 3 4 5 .
2 1 { i. 3 3 6 7 8 3 4 5
The left frame is 2; each atom of x selects an item of y (each a list), and the results are made into a 2x3-item array.
0 { 5 5
You are allowed to select item 0 of a scalar. This follows from the definition that a scalar has a single item which is the scalar itself. Selecting any other item is an error.
There are many variations on the format of x, providing for multidimensional indexing where each index can be a list. You will have to wait a bit to learn them, but I will note here that a negative index counts back from the end of the array:
_1 { 3 1 4 1 5 9 9 x # y (Copy)
Left rank is 1. If x is a list whose items are all 0 or 1, the result has the same rank as y, and contains just the items of y for which the corresponding item of x is 1. For example:
1 0 1 0 0 0 # 3 1 4 1 5 9 3 4 0 0 1 # i. 3 4 8 9 10 11 x -. y (Remove)
Both ranks are infinite. y is construed as a collection of cells whose rank is that of an item of x . Any items of x that match such cells of y are removed:
1 2 3 4 5 4 3 -. 2 4 1 3 5 3 (i. 4 2) -. (i. 2 2) 4 5 6 7 (i. 4 2) -. 0 1 2 3 4 5 6 7
In the last two examples, the items of x are 1-cells, so the 1-cells of y are removed from x . Understand the last example especially, to see that the shape of x determines how y is broken into cells.
The verb is defined with y operating on x because of the analogy with - . If x and y are sets, x -. y is the set difference.
Indexing: i. e. I.
x i. y (Index Of) and x i.!.0 y (Intolerant Index Of)
The left rank is infinite. x i. y looks through the items of x to find one that matches y; the result is the item number of the first match. Examples:
3 1 4 1 5 9 i. 5 4 (i. 4 3) i. 6 7 8 2
The comparison in dyad i. is tolerant, that is, numeric operands that are very close to equal are considered equal. The special form i.!.0 is like i., except that the comparison is intolerant. i.!.0 uses a different algorithm from i., and may be faster even if the operands are not numeric.
The rest of this discussion of dyad i. can be omitted until you need to apply <st2:middlename w:st="on">i.</st2:middlename> <st2:middlename w:st="on">I.</st2:middlename> e. or -. to arrays of rank 2 or higher.
The rank of the dyads <st2:middlename w:st="on">i.</st2:middlename> <st2:middlename w:st="on">I.</st2:middlename> e. -. is infinite, meaning the verb operates on both operands in their entirety, but they have the special peculiarity that they break up the data operand into cells based on the rank of the control operand.
Reread the definition of dyad i. . For y to match an item of x, the rank of y must be the same as the rank of an item of x (call that rix, which is one less than the rank of x (namely #$x) unless x is an atom; formally, rix is (0 >. (#$x) - 1) or, more cleverly, #${.x). If y is of higher rank, each rix-cell of y is matched against items of x . Formally, x i. y is equivalent to x i."(_,rix) y . Example:
3 1 4 1 5 9 i. 1 5 1 4 (i. 3 3) i. (i. 2 3) 0 1
The indexing operation is impossible if the rix-cells of y do not have the same shape as an item of x . Another way of saying this is that the shape of an item of x (}.$x) must be a suffix of the shape of y .
If an rix-cell of y matches none of the items of x, the result value for that cell is #x, i. e. one more than the largest valid item-number of x :
3 1 4 1 5 9 i. 8 4 _1 6 2 6
To be hair-splittingly accurate
we must say that x i. y
is equivalent to x i."(_,rix)"_ y because
the rank of dyad i.
is infinite. This distinction will
matter eventually.
x e. y (Element Of)
The right rank is
infinite. x e. y
is a lightweight version of y i. x; the result is 1 if x
matches an item of y,
0 if not. The verb is applied to riy-cells
of x (where
riy is the rank of an item of y). Formally, x e. y
is the same as (#y) ~: y i. x . Dyad e. is an exception
to the rule that x
is control information and y is data.
It was defined to be reminiscent of mathematical epsilon meaning
'element of'.
x I. y (Interval Index--Find Insert-Before Point In Sorted List)
The left rank is infinite. x must already be sorted in either ascending or descending order of its items. x I. y produces, for each rix-cell of y as defined above under x i. y, the index of the item of x before which y would be inserted into the sorted list. If more than one position is possible, the result is the smallest candidate; if the rix-cell of y would have to be put onto the end of x, the result is #x . You may think of x I. y as the index that y would have after it was inserted in its proper spot in the list x , or as the index of the interval (open on the left, closed on the right) containing y, where interval 0 includes any value coming before or equal to the first item of x .
1 3 5 7 7 9 I. 4 5 7 10 2 2 3 6
Take and Drop: {. }.
x {. y (Take) x }. y (Drop)
The left rank is 1, but the verb handles scalars also; we will consider only the case where x is a scalar. x {. y (take) takes the first x items of y, i. e. it produces a result which consists of the first x items of y; x }. y (drop) discards the first x items of y . If x is negative, x {. y takes the last (|x) items of y, and x }. y discards the last (|x) items (remember, |x is the absolute value of x). The rank of the result is always the same as the rank of y, and in all cases the order of items is unchanged. Examples:
2 {. 3 1 4 1 5 9 3 1 2 }. 3 1 4 1 5 9 4 1 5 9 _2 {. 3 1 4 1 5 9 5 9 _1 }. i. 3 3 0 1 2 3 4 5
x {. y always gives you as many items as you asked for. If you overtake by asking for more than #y items, J will create extra ones, filling them with 0 or ' ' as appropriate:
5 {. 3 1 4 3 1 4 0 0 _5 {. 'abc' abc NB. Negative overtake: fills added at front
We have met fills before; they were added to bring the results from different cells of a verb up to a common shape so that they could be made into an array. The fills added by overtake are different: they are part of the execution of the verb itself. We will distinguish the two types of fill, calling the ones added by the verb itself verb fills and the ones added to make cell-results compatible framing fills. Framing fills are always 0 or ' ', but you can specify the value to use for a verb fill, using the fit conjunction !. :
5 {.!.9 (3 1 4) 3 1 4 9 9 _5 {.!.'x' 'abc' xxabc
The fit conjunction creates a new verb; in this case {.!.f is a verb that looks just like {. but uses f for the verb fill.
The fit conjunction is by no means reserved for specifying verb fills: it is available for use on any primitive to make a small change to the operation of the primitive. If !. has a meaning for a primitive, that meaning is given in the Dictionary entry for the primitive.
Joining Arrays: ,. ,:
x ,. y (Stitch)
The left rank is infinite. x ,. y is equivalent to x ,"_1 y . That means that dyad , is applied to the corresponding items of x and y, making each item of the overall result the concatenation of the corresponding items. Example:
3 4 5 ,. 7 8 9 3 7 4 8 5 9 x ,: y (Laminate)
The left rank is infinite. x ,: y is a list of 2 items: item 0 is x and item 1 is y . If x and y do not have the same shape, they are brought to a common rank and padded with fills to a common shape. Dyad ,: concatenates x and y along an added axis, in contrast to dyad , which concatenates them along their leading axis:
3 4 5 ,: 7 8 9 3 4 5 7 8 9
Contrast this with dyad ,. above or dyad , which would produce 3 4 5 7 8 9 .
1 2 , 3 4 ,: 5 6 1 2 3 4 5 6
Take a moment to understand why in this example the first verb is dyad , and the second is dyad ,: .
Rotate Left and Shift Left: |.
x |. y (Rotate Left)
The left rank is 1, but we will discuss only the case where x is a scalar. The result has the same shape as y, with the items of y rotated x places to the left (with wraparound). If x is negative, the items are rotated to the right. Examples:
2 |. 3 1 4 1 5 9 4 1 5 9 3 1 _1 |. i. 3 3 6 7 8 0 1 2 3 4 5 x |.!.f y (Shift Left)
When the fit conjunction is used, any item that is rotated across the beginning of y is replaced by the fill f . This turns the rotate into a shift where f gives the value to be shifted in:
2 |.!.'x' 'abcde' cdexx _2 |.!.'x' 'abcde' xxabc
Sort: /: \:
x /: y (Sort Up Using) x \: y (Sort Down Using)
The left rank is infinite. x must have at least as many items as y. The items of x are records and the items of y are keys; x /: y is the records x sorted into ascending order of corresponding keys y . x \: y sorts into descending order. Examples:
3 1 4 1 5 9 /: 0 1 2 3 4 5 3 1 4 1 5 9
y was already in order.
3 1 4 1 5 9 /: 5 4 3 2 1 0 9 5 1 4 1 3
Sorting into reverse order.
3 1 4 1 5 9 /: 0 10 1 20 2 30 3 4 5 1 1 9
x in order of ascending y .
(i. 4 3) /: 10 20 1 2 6 7 8 9 10 11 0 1 2 3 4 5
Items of x in order of ascending y .
1 3 5 /: 7 8 , 1 2 ,: 4 5 3 5 1
The keys y do not have to be single numbers; they don't even have to be numeric. Here, 1 2 is lowest, then 4 5, then 7 8 . The Dictionary gives complete rules for ordering y .
Because sorting is not so easy in C, C programmers are not quick to recognize applications of /: and \: . The J implementation of /: and \: runs in linear time for most y and should not be avoided.
According to our general
principle, we would expect that in dyad /: x
held the keys and y
the data. Dyad /: is an exception
to the rule (the reasoning is that in both x /: y
and /: y,
y
holds the ordering information).
y /: y or /:~ y (Sort Up) y \: y or \:~ y (Sort Down)
When x and y are the same, you have the simple case of sorting y into ascending or descending order. We will learn later that u~ y is equivalent to y u y, so /:~ y and \:~ y can be used to sort y into ascending or descending order.
Match: -:
x -: y (Match)
The left rank is infinite. The result is 1 if x and y are the same, 0 otherwise, except: (1) if they are numeric, the comparison is tolerant; (2) for some reason I don't understand, if they are empty, they are considered to match even if the types are different, which means that getting a result of 1 from x -: y is no guarantee that x and y will behave identically:
(0$0) -: '' 1 (1 {. 0$0) -: (1 {. '') 0
The important difference between dyad -: and dyad = is that dyad -: has infinite rank so you get a single result covering the entire array, and it won't fail if the shapes of x and y do not agree.
Monads
Enfile: ,
, y (Enfile)
, y consists of all the atoms of y, made into a list. The order is row-major order , i. e. all the atoms of item 0 of the original y come first, followed by atoms of item 1, and so on; within each item the ordering similarly preserves the order of subitems. Examples:
, i. 2 3 0 1 2 3 4 5
The atoms were made into a list.
a =. 2 2 3 $ 'abcdefghijkl' a abc def ghi jkl ,a abcdefghijkl
y of any shape produces a list.
Recall that a single quoted character is an atom rather than a list:
$'x'
To get a 1-character list, use monad , :
$,'x' 1
The official name for monad , is the quaint but unedifying 'ravel', meaning 'separate or undo the texture of'. I prefer the equally quaint but more descriptive 'enfile', which means 'arrange in a line (as if on a string)'.
Reverse and Transpose: |. |:
|. y (Reverse)
The items of y are put into reverse order:
|. i. 5 4 3 2 1 0 |: y (Transpose)
The axes of y are reversed. This is difficult to visualize for high ranks but easy for the most common case, rank 2:
|: i. 3 4 0 4 8 1 5 9 2 6 10 3 7 11
The dyad x |: y is similar, but rather than simply reordering the axes, the verb permutes them by moving the axes specified in x to the end of the shape.
Take and Drop Single Item: {. {: }. }:
{. y (Head) {: y (Tail) }. y (Behead) }: y (Curtail)
The operations performed are simple; the biggest problem is remembering which primitive does what. Remember that { means take and } means drop, and that . means beginning and : means end. So, {.y is the first item of y, {:y is the last item of y, }.y is all of y except the first item, }:y is all of y except the last item:
{. 3 4 5 3 {: i. 3 4 8 9 10 11 }. 3 4 5 4 5
}.y is identical to 1}.y and }:y is identical to _1}.y . {.y is not identical to 1{.y, because 1{.y has the same rank as y while {.y has the rank of an item of y .
Grade (Create Ordering Permutation): /: \:
/: y (Grade Up) \: y (Grade Down)
/: y creates a numeric list with #y items, such that i{/:y is the index of the ith-largest item of y . (/:y){y gives y sorted into ascending order. /:y is a permutation vector, i. e. it contains each integer in the range 0 to (#y)-1. \: is similar but works in descending order. Example:
/: 3 1 4 1 5 9 1 3 0 2 4 5
Read this result as follows: the smallest item of y is item 1 (with value 1), the next-smallest is item 3 (1), then item 0 (3), then item 2 (4), then item 4 (5), then item 5 (9). Monad /: defined this way turns out to be surprisingly useful. As a limbering-up exercise in the use of permutation vectors, and an example of how compactly J can express ideas, see if you can describe in words what two applications of monad /: will give:
/: /: 3 1 4 1 5 9 2 0 3 1 4 5
Add An Axis: ,: (Itemize)
,: y
The result of ,: y has rank one higher than the rank of y, with one item, which is y . The shape of ,: y is the shape of y with 1 prepended (in plain J, $,:y is 1,$y).
Constant Verb
m"n
We have met the rank conjunction " applied to verb left arguments; applied to noun left arguments it produces a verb whose result is always the value of the noun. The created verb (which can be used as either a monad or a dyad) has ranks, given as the right operand of " . Examples:
5"_ i. 4 4 5
The simplest and most common case. Since the verb has infinite rank, it operates on the entire operand and produces the scalar value.
5"0 i. 3 5 5 5
Here the verb is applied to each 0-cell of the list, giving the scalar result for each cell.
1 2 3"0 i. 3 1 2 3 1 2 3 1 2 3
Here the result at each cell is the left argument of " , the list 1 2 3 . If you were expecting the 3 to be repeated, remember that you can look at the words as J sees them:
;: '1 2 3"0 i. 3' +-----+-+-+--+-+ |1 2 3|"|0|i.|3| +-----+-+-+--+-+
1 2 3 is a single word.
_9:..._1: 0: 1:...9: _: __:
For a few special values, namely the integers _9 through 9, infinity _, and negative infinity __, you can create an infinite-rank verb to produce the value by following the constant value with : . This is equivalent to value"_ .
3: 'abc' 3
The operand 'abc' was ignored, and the result was 3 .
>> << Pri JfC LJ Phr Dic Voc !: Rel NuVoc wd Help J for C Programmers