# Vocabulary/EZRank

# Rank in a hurry

## Contents

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

or:

box=: (3 : 0)"1 < y )

or:

box=: <"1

or (most straightforward of all):

boxall=: < box=: boxall"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`, `_` .

**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:

The *J NuVoc* title page summary shows similar information:

## 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

- Rank (
`"`) - Atop (
`@`) - At (
`@:`) - Fork
- Cap (
`[:`) - Entry in the J Dictionary for Rank (
`"`) - J Dictionary, Introduction, Section 20. Rank
- J for C Programmers Chapter 6, Loopless Code I: Verbs Have Rank