This page explains the concept of verb rank.
Every verb has a verb rank. It determines the cell of the y-argument (and x-argument) to which the verb gets applied.
Typical loops in a non-APL
Typical looping tasks you'd perform in a non-APL, i.e. a non- Array Processing Language:
1. Loops that do the same thing to each item of a given list 2. Loops that do different things to each item of a given list 3. Loops that do a given thing jointly to all the items of a given list, e.g. find the largest item 4. Loops applied to regular subsets of the given list 5. Loops applied to irregular subsets of the given list 6. Loops that carry over information from one iteration to the next 7. Loops that implement some finite-state machine.
Let's examine the easiest case (1. above) first.
J has a simple way of doing the same thing to each item of a given list. We call this an implicit loop because it's not clear to a non-J programmer that J is doing a loop. Why not? Because a non-J programmer will probably be looking for an explicit looping construct – and not see it. Nevertheless some sort of loop is implied, in other words a loop is implicit.
Examples of Implicit Loops
In the following examples
- The dyad: Plus (+) adds numbers x and y
2 + 3 5
- The monad: Integers (i.) makes an array of shape y
i. 2 3 0 1 2 3 4 5
If y is an array, (y+2) gives us the simplest example of an implicit loop.
At each iteration, the items of y are taken in turn and the number 2 gets added to that particular item
y =: 3 4 5 2 + y 5 6 7
If both x and y are lists, then at each iteration, the items of y are taken in turn and the corresponding item in x gets added to that item in y
y =: 3 4 5 x =: 0 1 2 x + y 3 5 7
By corresponding item in x, we mean
- item 0 of x gets added to item 0 of y
- item 1 of x gets added to item 1 of y
- item 2 of x gets added to item 2 of y
- ...and so forth.
DEFINITION: If lists x and y have the same number of items, then we say that they agree.
But what if x and y don't have the same number of items, i.e. they don't agree? Then J refuses to add x and y. Instead J signals a length error
y =: 3 4 5 x =: 0 1 x + y |length error | x +y
If y is not a list of numbers, but a list of lists of numbers (i.e. a table)
] y =: i. 2 3 0 1 2 3 4 5 x =: 0 100 x + y 0 1 2 103 104 105
Look what happens:
- J does not signal a length error, even though x and y have a different number of numbers, i.e. they have different shapes.
However they do have the same number of items – i.e. they do agree.
- In x the items are individual numbers – x has two such items
- In y the items are rows of numbers – y has two such items.
- The (two) atoms of x get added to the (two) rows of y, exactly as in Example 1 above.
- The monad: Base 2 (#.) makes an integer out of the binary numeral y – i.e. a numeral (a list of digits) consisting of the digits 0 and 1 only
#. 1 0 0 1 9 #. 1 0 1 5
- The monad: Antibase 2 (#:) does the inverse action, i.e. it makes the binary representation of the integer y – i.e. the representation of y as a binary numeral
#: 9 1 0 0 1 #: 5 1 0 1
MNEMONIC: (to help you remember which is which)
- (#.) with a single dot makes an atom (from a list)
- (#:) with more than one dot makes a list (from an atom).
Both these primitives work with arrays in place of single numbers
] y =: #: 9 5 1 0 0 1 0 1 0 1 #. y 9 5
Look what happens: Antibase 2 (#:) converts integers to lists as follows
- 9 --> (1 0 0 1) – as we saw above
- 5 --> (1 0 1) – as we saw above
- (1 0 1) --> (0 1 0 1) – an equivalent binary numeral.
The final step is needed to make a rectangular array out of the two items which make up y, viz. the binary representations of 9 and 5
But notice something important: Base 2 (#.) works in a rather different way to a monad such as Negate (-)
- (-) gets applied to individual numbers of y, negating each number
- (#.) gets applied to entire rows of y, treating each row (=list) as a binary representation
- y _1 0 0 _1 0 _1 0 _1 #. y 9 5
How does J know that Negate (-) needs to be applied to individual numbers, but Base 2 (#.) needs to be applies to entire rows?
The answer lies in their verb ranks – which happen to be different.