Vocabulary/EZRank

From J Wiki
Jump to navigation Jump to search

Back to: Vocabulary

Rank in a hurry

This is not a complete exposition, nor is it a scholarly one. It's for you if

  • you are new to J
  • you have a rank problem
  • you're in a hurry.

See bottom of this page for links to authoritative expositions of the concept of rank.

J authors tell you that you must understand rank fully in order to make progress in learning J.

True enough, but this page tells you all you need to know for now.


Q. How do I know if I have a rank problem?

A. Your data gets chunked-up in the wrong way.

Q. Okay... Box (<) is chunking-up my noun y in the wrong way. I want to box the rows of y, not the whole of y

   ] y=: 2 3$'abcdef'
abc
def
   <y
+---+
|abc|
|def|
+---+

A. Try suffixing the offending verb with:

"0 verb acts on each atom
"1 verb acts on each row
"_ verb acts on the whole noun in a lump
   <"0 y
+-+-+-+
|a|b|c|
+-+-+-+
|d|e|f|
+-+-+-+
   <"1 y
+---+---+
|abc|def|
+---+---+
   <"_ y   NB. same as plain (`<`), but only in this example.
+---+
|abc|
|def|
+---+

If you are defining your own verb, e.g. box, then use Rank (") like this, to give it a rank of 1.

   box=: (3 : '< y')"1   NB. (parentheses are actually redundant here)

or:

   box=: (3 : 0)"1   NB. (parentheses are actually redundant here)
< y
)

or (most straightforward of all):

   box=: <"1

Q. How do I box the columns of y instead of the rows?

A. Transpose y (for now)

   <"1 |:y
+--+--+--+
|ad|be|cf|
+--+--+--+

But in practice you won't need to do this much.

A noun has a natural hierarchy: table --> list --> atom.

  • In J, a matrix (of any noun rank) is a table, which itself is a list of lists, or maybe a list of tables.
  • A 2-D matrix is a list of lists of atoms.
  • A 3-D matrix is a list of 2-D matrixes, i.e. a list of lists of lists of atoms.
  • and so on.

In each case the innermost lists correspond to the rows of the matrix.

Those J primitives for which y is basically not just a single atom but a list of atoms all take account of this.

e.g. Base 2 * Base (#.), Reverse * Rotate (Shift) (|.)

If you want an easy ride, it's worth structuring your data in the same way.


Q. Rank isn't working for me!

   ] y=: ;:'The QUICK Brown box'
+---+-----+-----+---+
|The|QUICK|Brown|box|
+---+-----+-----+---+
   toupper y
+---+-----+-----+---+
|The|QUICK|Brown|box|
+---+-----+-----+---+
   toupper"0 y
+---+-----+-----+---+
|The|QUICK|Brown|box|
+---+-----+-----+---+
   toupper"1 y
+---+-----+-----+---+
|The|QUICK|Brown|box|
+---+-----+-----+---+
   toupper"_ y
+---+-----+-----+---+
|The|QUICK|Brown|box|
+---+-----+-----+---+

toupper is a

  • Standard Library word(s) residing in the 'z'-locale
  • Defined in the factory script stdlib.ijs which is located in  ~system/main/stdlib.ijs
  • View the definition(s) in a JQt session by entering:  open '~system/main/stdlib.ijs'

A. That's because you don't have a rank problem - you have a type problem.

Verb toupper will accept any type of noun, but does nothing unless the type is literal. The trouble with your noun y is that it has type: boxed, not: literal.

Remember: a list must consist of items all of the same type.

To find the type of a given noun y, use: datatype

  datatype y
boxed

datatype is a

  • Standard Library word(s) residing in the 'z'-locale
  • Defined in the factory script stdlib.ijs which is located in  ~system/main/stdlib.ijs
  • View the definition(s) in a JQt session by entering:  open '~system/main/stdlib.ijs'

Q. How do I work round this problem?

A. You need to open y to reveal the characters inside, so that toupper can get at it.

  datatype y
boxed
   datatype > y
literal

There are 3 ways you can try:

1. Simply use Open (> y) -- but that changes the structure of y

   toupper > y
THE
QUICK
BROWN
BOX

2. Use each

   datatype each y
+-------+-------+-------+-------+
|literal|literal|literal|literal|
+-------+-------+-------+-------+
   toupper each y
+---+-----+-----+---+
|THE|QUICK|BROWN|BOX|
+---+-----+-----+---+

each is a

  • Standard Library word(s) residing in the 'z'-locale
  • Defined in the factory script stdlib.ijs which is located in  ~system/main/stdlib.ijs
  • View the definition(s) in a JQt session by entering:  open '~system/main/stdlib.ijs'

3. Use Under (&.) directly - which is itself used by each

   toupper &.> y
+---+-----+-----+---+
|THE|QUICK|BROWN|BOX|
+---+-----+-----+---+

This says, in effect, "apply toupper to y under the the action of: (>)", which means: firstly open y (item-by-item) and then close it again.

For details, see: Under (Dual) (&.)


Still got problems? Then read on...

The rank of a noun

The rank of a noun y is just the number of atoms in its shape $y

Rank applies to... Example Another example
0 atoms 1.56 'a'
1 vectors, lists of atoms, strings i.6 'abc'
2 2-D matrixes i.2 3 2 3$'abcdef'
3 3-D matrixes i.2 3 4 2 3 4$'abcdefghijklmnopqrstuvwx'

But that's only part of the story...

The rank of a verb

A verb, too, has a (verb) rank, whether it's a primitive or a user verb. The rank determines the shape of the cell (the chunk of y) it chooses to work on. A cell of rank n is called an n-cell. A verb which tries to work on an n-cell is said to have rank n.

But unlike a noun, a verb can also have infinite rank, or negative rank. These both need you to know the rank of y (and x too, for the dyadic case), to predict the actual n-cell that gets worked on.

  • Infinite rank means the biggest possible n for given y, i.e. the whole of y.
  • Negative rank means work backwards from the actual rank of y to arrive at n for the actual n-cell worked on.

The vast majority of primitive verbs have rank 0, 1 or _

One exception: Matrix Inverse * Matrix Divide (%.) -- which has rank 2.

More elaborate verbs, which need a matrix or a table as y, may have other ranks than 0, 1, _ .

(Simple) Verb Rank example
Append (,) and Insert (/) interpreting a dyadic verb's arguments as list or atoms:

    2 3 5 (,/"1 0) 101 103     NB. left: list; right: atoms
2 3 5 101
2 3 5 103
    2 3 5 (,/"0 1) 101 103     NB. left: atoms; right: list
2 101 103
3 101 103
5 101 103

Q. How do I find the rank of a given verb?

A. Use the adverb b.0, which is formed from the conjunction Basic (b.)

   < b.0
_ 0 0
   toupper b.0
_ _ _

   sum=: +/
   sum b.0
_ _ _

Note the following: The full specification for the rank of a verb is not a single number but a 3-list:

  • 1st number: the rank of monadic u for chunking-up y (the sole argument)
  • 2nd number: the rank of dyadic u for chunking-up x
  • 3rd number: the rank of dyadic u for chunking-up y.

If you create a verb e.g. u"1 and provide only one number for its Rank then it is used for the value of all three numbers.

   sum=: +/
   sum b.0
_ _ _
   rowsum=: sum"1
   rowsum b.0
1 1 1
   ] y=: i.2 3
0 1 2
3 4 5
   sum y
3 5 7
   rowsum y
3 12

For most J primitive verbs, all three numbers are indeed the same. But they are apt to differ when a given word stands for two substantially different verbs in its monadic and dyadic usage.

This is the case (as we saw above) with Box (<) and Less Than (<).

   < b.0
_ 0 0

Here the first number (_) is the rank of Box (<)

Box is a monad, and it chooses to work on the biggest possible n-cell within y

Whereas the second and third numbers (both 0 here) apply to Less Than (<)

Less Than is a dyad, and it chooses the smallest possible n-cell to work on, viz. individual numbers.

Q. How can I look up the rank of a given primitive, if I haven't got a J session running?

A. The J Dictionary shows it, for each J primitive (e.g. <) in its individual page in the Dictionary.

Provided the primitive is a verb, the triple-number rank specification is shown in the middle of the top line of the page:

Rank spec m 0.png

The J NuVoc title page summary shows similar information:

Rank spec m 1.png


An insidious rank problem

A rank problem can turn up unexpectedly when combining verbs u and v in a tacit phrase.

In mathematics, the composition of functions f and g is usually defined as: (f (g (y)) .

You can express it as a tacit verb phrase by means of a train of verbs (([: u v)) called a fork, or by forming (u&v), (u@v) or (u@:v). But make sure you pick the right one for your purpose, because they occasionally give different results!

Consider the different ways of forming the composition of two verbs: mean and cat

   mean=: +/ % #
   cat=: ,&1"1
   ]z=: i.2 3       NB. sample noun
0 1 2
3 4 5
   cat z            NB. appends 1 to each row of z
0 1 2 1
3 4 5 1

   mean@cat z       NB. mean of the ROWS of cat z
1 3.25
   mean&cat z       NB. mean of the ROWS of cat z
1 3.25
   mean@:cat z      NB. mean of the COLUMNS of cat z
1.5 2.5 3.5 1
   ([: mean cat)z   NB. mean of the COLUMNS of cat z
1.5 2.5 3.5 1

The reason for the difference comes down to the rank of the chosen method of composition

   mean b.0
_ _ _
   cat b.0
1 1 1
   mean@cat b.0        NB. works on n-cells (i.e. 1-cells) consisting of the ROWS of y
1 1 1
   mean&cat b.0        NB. ditto
1 1 1
   mean@:cat b.0       NB. works on a single n-cell consisting of the WHOLE of y
_ _ _
   ([: mean cat) b.0   NB. ditto
_ _ _

Clearly our original definition of the composition of u and v wasn't precise enough. But we can state precisely:

  • u@:v"v and u@v are equivalent
  • ([: u v) and u@:v are equivalent
  • ([: u v)"v and u@v are equivalent, i.e. u@v has the same rank as v.

and if u and v are monads,

  • u&v and u@v are equivalent


See Also