# Array Manipulation

Computing with rectangular array structures in J |

--> For more **details** about and options for a specific action, click on the naming line above its explanation.

--> In the text and examples here, y represents the right argument to a verb; x represents the left argument to a dyadic verb. For an explanation of **monadic/dyadic** verb distinctions, see Vocabulary/Valence.

**Rectangular arrays** are the homes for data values in the J language. The J Engine supplies tools for building these homes, warehouses, and apartments, much like lining up square or cubical building blocks--sometimes in even more dimensions. Numerical and character values are the *nouns* of the J language. The Engine is instructed through *verbs* to perform basic tasks, with *adverbs* to control where and how to perform them, and *conjunctions* to combine a few of them to work together in sequence or alternation. The supplied *primitive* actions may be combined into more advanced tools by *definition* and *assignment*, and a set of those may be stored in a *script* to describe how to build a whole city of data structures.

Not all datasets arrive in fully rectangular arrays. Some can be treated by extending smaller subsets with *fill values*, which are ignored in some operations or explicitly excluded from others. An alternative is to enclose lowest levels, with varying amounts of data, in *boxes* which can then be lined up and stacked more uniformly; operations on them will then have to open each box to determine its value when needed.

## Forming

**Generating integer arrays**: *Integers*

*Integers* (monadic `i.`) returns an ascending (or descending) sequence of integers, wrapped to the shape specified by (`|` y).

i. 6 0 1 2 3 4 5 i. 2 3 0 1 2 3 4 5 i. 6 1 0 1 2 3 4 5

**Creating other arrays**: *Reshape*

*Reshape* (dyadic `$`) creates an array whose shape--the lengths of successive axes--is specified by the integer values in x, followed by the shape of y's items. Its items are the items (sub-arrays, which may or may not be atoms) of y, taken in order, and repetitively as needed. The Tally of y becomes irrelevant.

2 3 $ 'ab' aba bab 2 3 $ i. 2 4 NB. A 2x3 array of 4-atom lists: of shape 2 3 4 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 4 3 $ , i. 2 4 NB. Raveling before reshaping: re-arranging atoms 0 1 2 3 4 5 6 7 0 1 2 3

**Entering a table**: *Define*

*Define* (dyadic `:`) helps you enter a table line-by-line, as you would prefer to visualize it--e.g., a 2-by-3 table. This creates a linefeed-separated character string. The library verb cutopen can box each "line", forming a list. The Numbers or Do verbs (".) can convert opened boxes to internal numerical format, and stack them as a table.

NB. Executing unboxed character strings found between linefeeds in input n=: ". > cutopen noun define NB. Stores 2 x 3 table 100 101 102 200 201 202 )

**Joining atoms and lists**: *Append*

*Append* (dyadic `,`) creates a new array consisting of copies of all the items of x followed as a group by those of y . (See *Stitch*, below, for joining item-by-item.) When their shapes differ along any axis after their leading 0-axes, the shorter ones are extended with fill values to match the longer ones.

If x and y are atoms or lists, (x,y) is simply a list made from x followed by y .

z=: i. 6 NB. Listing 6 integers z , 99 0 1 2 3 4 5 99 99 , z 99 0 1 2 3 4 5 z , 99 100 0 1 2 3 4 5 99 100

**Joining arrays' items**: *Stitch*

*Stitch* (dyadic `,.`) appends a copy of each *item* of `x` to a copy of the corresponding item of `y` . (This is appending at rank _1, i.e. (,"_1) .)

If either `x` or `y` is an atom, it is appended to each item of the other.

x ; y =: toupper x=: 3 5 $ 97 }. a. NB. Two linked Alphabet selections +-----+-----+ |abcde|ABCDE| |fghij|FGHIJ| |klmno|KLMNO| +-----+-----+ x ,. y abcdeABCDE fghijFGHIJ klmnoKLMNO x ,. '/' NB. Stitching a character atom abcde/ fghij/ klmno/ '\' ,. y \ABCDE \FGHIJ \KLMNO

**Stacking arrays**: *Laminate*

*Laminate* (dyadic `,:`) creates a two-item array (with rank at least 2) whose first item comes from `x` and whose second item comes from `y` . (This creates a new leading axis, by appending at highest rank, i.e. (`,"_`) .) When their shapes differ along any axis, the shorter ones are extended with fill values to match the longer ones.

x=: 'alpha' y=: 'bravo' ] z=: x ,: y NB. x becomes item 0; y becomes item 1 alpha bravo $z 2 5 #z 2

**Enclosing arrays**: *Box*

*Box* (monadic `<`), also known as *Enclose*, returns a boxed form of the noun y, a type of atom. It can then join in an array with other boxes, regardless of the nature of the contents of those boxes. Arrays in J must contain only atoms of the same type, but any noun in a box becomes an atom that can be arrayed with any other boxes. Boxes can therefore help to create arrays containing heterogeneous values.

Strings of varying length can't make a uniform table without appending some trailing fill values, but *Words* (`;:`) can box each word of a character string, as is, to join with the others.

*Link* (dyadic `;`) can join dissimilar types after insuring boxing.

*Open* (monadic `>`), also known as Disclose, can remove contents from an array of boxes, but only when those contents are all of compatible datatypes. Each box's contents will have fill values appended wherever necessary to match the maximal rank and sizes in the batch.

< 1 2 3 +-----+ |1 2 3| +-----+ < 'abc' +---+ |abc| +---+ ;: 'Three different words' NB. Words (<tt>;:</tt>) parses, boxes, then joins. +-----+---------+-----+ |Three|different|words| +-----+---------+-----+ < > ;: 'Three different words' +---------+ │Three │ │different│ │words │ +---------+

## Inspecting

**Finding size**: *Tally*

*Tally* (monadic `#`) counts the items in y. The items of an array are the cells whose rank is 1 lower than the rank of the array. Thus, the items of a rank-1 list are atoms, and the items of a table are lists.

An atom has one item, i.e. itself.

# 'abc' 3

**Finding shape**: *Shape of*

*Shape of* (monadic `$`) a noun is...

- empty (
`i.0`) for an atom (e.g. the single character 'a') - the number of atoms in a list (e.g. a list of numbers)
- 0 for an empty list (of rank 1)

- (2 3) for a 2-by-3 table.

$ 'abc' NB. A 3-atom list 3 $ 'a' NB. 1 atom - no axes: gives empty response $ '' NB. An empty list - 1 axis, 0 elements 0 $ i. 2 3 NB. A 2-by-3 table (of rank 2) 2 3 ] empty =: 0 # i. 3 4 NB. Creating a table, then deleting all the rows $ empty NB. The rows are still 4 long, even though there are 0 of them! 0 4

**Finding rank**: *Tally* and *Shape of*

Find the rank of a noun using *Tally* and *Shape of*: `# $ y` .

# $ 'a' NB. Rank of an atom is 0 0 # $ 'abc' NB. Rank of a list of atoms is ALWAYS 1 1 # $ '' NB. ... even for an empty list 1 # $ i. 3 2 NB. An array of rank 2 is called a table 2

**Finding type**: *datatype*

All the items of any array are stored in a common machine format, appropriate to its datatype: Boolean / literal / integer / floating / complex / boxed / extended / rational / sparse / unicode. Boolean and any numerical values combine according to various conversion rules to achieve a common format. Literal (ASCII) and Unicode characters may also combine after conversion.

datatype '4' literal datatype 4 integer '4', 4 |domain error | '4' ,4

## Reforming

**Reshaping**: *Reshape*

*Reshape* (dyadic `$`) creates an array whose shape is the integer values in x followed by the shape of an item of y, whose *items* are copied serially (and repetitively) to fill the specified shape.

2 3 $ 'ab' NB. Reshaping atom-by-atom aba bab 2 3 $ i. 2 4 NB. Reshaping row-by-row 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7

**Replicating**: *Copy*

*Copy* (dyadic `#`) creates a new array in which each non-negative integer in x controls how many times the corresponding item of y appears. See also Copy 2.

3 # < 3 1 4 NB. Repeating a single atom (a box) ┌─────┬─────┬─────┐ │3 1 4│3 1 4│3 1 4│ └─────┴─────┴─────┘ 3 # 3 1 4 NB. Repeating every atom 3 3 3 1 1 1 4 4 4 1 2 0 3 # 'abcd' NB. Repeating each item independently abbdddd

**Reversing**: *Reverse*

*Reverse* (monadic `|.`) copies the items of y in reverse order.

|. i.6 NB. Reversing a list 5 4 3 2 1 0 i. _6 NB. A special case of Integer generation 5 4 3 2 1 0

**Rotating**: *Rotate*

*Rotate* (dyadic `|.`) copies the items of y, skipping x positions, then appends copies of the skipped items at the end.

2 |. i.6 NB. Rotating headward by 2 (leftward, upward, topward, ...) 2 3 4 5 0 1 _1 |. i.6 NB. Negative x => tailward, etc. 5 0 1 2 3 4

**Transposing axes**: *Rearrange*

*Rearrange* (dyadic `|:`) creates a copy of array y, reorganized so that the new last axes are the axes numbered as listed in x, preceded by any unspecified axes in their original relative order.

ii=: ] {. [: i. 10 #~ # NB. Utility verb to make self-indexing array ] y =: ii 2 3 4 NB. Rank-3 array (of distinct axis sizes) 0 1 2 3 10 11 12 13 20 21 22 23 100 101 102 103 110 111 112 113 120 121 122 123 NB. Copying with axis 0 at end. Old axes 1 and 2 become new axes 0 and 1 0 |: y 0 100 1 101 2 102 3 103 10 110 11 111 12 112 13 113 20 120 21 121 22 122 23 123 $ y 2 3 4 $ 0 |: y NB. New shape shows original axis 0 (size=2) is now the last axis 3 4 2

**Listing all atoms**: *Ravel*

*Ravel* (monadic `,`) produces a list containing all the *atoms* in y, in the order in which they appear in the display of y (from topmost-headmost-leftmost to the farthest end). Note that the atoms may be boxes, which may be re-ordered, but not opened or internally raveled.

] z=: 0 20 10 +/ i.4 NB. Sample noun 0 1 2 3 20 21 22 23 10 11 12 13 , z 0 1 2 3 20 21 22 23 10 11 12 13 NB. Raveling to atomic level

**Joining incompatible arrays**: *Link*

*Link* (dyadic `;`) joins two arrays, of possibly dissimilar types, after insuring boxing, to build up a list of boxed items.

Note: (x ; y) always (re-)boxes x, but *boxes y only if it is empty or not boxed*. This makes it easier to create lists of more than two singly-boxed items from a right-to-left sequence of linkings.

0 2 ,: 4 2 5 7 NB. Direct joining of unequal lengths can introduce fill values 0 2 0 0 4 2 5 7 0 2 ; 4 2 5 7 NB. Boxing preserves individual lengths internally +---+-------+ |0 2|4 2 5 7| +---+-------+ 'alpha' ; 'bravo' ; 'charlie' +-----+-----+-------+ |alpha|bravo|charlie| +-----+-----+-------+ _2 ]\ 'front nine'; 36; 'back nine'; 38 NB. Displaying list as length-2 Infixes +----------+--+ |front nine|36| +----------+--+ |back nine |38| +----------+--+

**Merging boxed items**: *Raze*

*Raze* (monadic `;`) removes one level of boxing from a noun. It copies the contents of each highest-level box, making each of its cells become an item of the result.

The shape of y is immaterial. If the contents of the boxes in y are atoms or lists, the result is to run the contents together into a single unboxed rank-1 list. The merged items must all be at level 0 (unboxed), all at level 1 (singly boxed), or all at higher levels, to avoid boxed-vs.-unboxed domain errors.

] y=: 'alpha' ; 'bravo' ; 'charlie' +-----+-----+-------+ |alpha|bravo|charlie| +-----+-----+-------+ ; y alphabravocharlie

**Sorting**: *Sort*

*Sort* (dyadic `/:`) sorts a copy of x using the order given by y (a slightly counter-intuitive relationship). It applies to list x the permutation that sorts list y into ascending (`/:`) or descending (`\:`) order, whether numerical or lexicographical. Formally, (x /: y) is ((/: y) { x).

If x and y are the same noun, the result is that noun is sorted into order. A convenient way to specify that operation is to use the Reflex adverb (`~`) in (/:~ y).

] Wk=: ;: 'Su Mo Tu We Th Fr Sa' NB. Parsing via Words +--+--+--+--+--+--+--+ |Su|Mo|Tu|We|Th|Fr|Sa| +--+--+--+--+--+--+--+ (100+i.7) /: Wk NB. Sorting numerical list per names 105 101 106 100 104 102 103 /:~ Wk NB. Sorting day names +--+--+--+--+--+--+--+ │Fr│Mo│Sa│Su│Th│Tu│We│ +--+--+--+--+--+--+--+

**Permuting**: *Permute*

*Permute* (dyadic `C.`) applies the permutation x to a copy of the items of y.

1 3 0 2 C. 'abcd' NB. Direct form of permutation: same as x { y bdac (1 2 ; 3 0) C. 'abcd' NB. Cycle form: exchanging items 1 & 2, 3 & 0 dcba

**Replacing (substituting) elements**: *Amend*

*Amend* (`}`) is an adverb that uses a preceding index list to produce a verb which copies y, while replacing the values at those positions with corresponding values from x. More structured boxed lists of indices can specify scattered subsets in higher-rank arrays.

NB. Replacing items at positions 0 and 3 with 'g' and 'w' respectively 'gw' 0 3} 'cross' grows NB. Substituting the same atom at several positions '*' 0 2 4 6} 'abcdefghijklmnop' *b*d*f*hijklmnop

## Searching

**Searching for specific value(s)**: *Member in*

*Member in* (dyadic `e.`) returns 1 for each rank-specified cell in x found anywhere in array y, otherwise 0. y is viewed as a list of its items, and each cell of x that has the same rank as the items of y is checked to see if it matches any of them. The result contains one Boolean atom for each cell of x.

'a' e. 'alpha' NB. Yes, the atom 'a' IS in the literal list 1 'd' e. 'alpha' NB. No, the atom 'd' is NOT in 'alpha' 0 'a' e. 1 2 3 NB. Character 'a' is not in numeric list. (No error signalled) 0 'bz' e. 'abracadabra' NB. Testing multiple atoms at once 1 0

**Locating specific value(s)**: *Index of*

*Index of* (dyadic `i.`) reports the position in x of the first occurrence of each item of y. For each item of y not found in list x, (x i. y) returns (#x)--beyond its last position.

'abracadabra' i. 'r' 2 'abracadabra' i. 'acjd' NB. Several search values 0 4 12 6

**Locating specific sequence(s)**: *Matches*

*Matches* (dyadic `E.`) creates a Boolean array indicating starting points (upper-left, 0 0...) in y of subarrays equal to x.

If x and y are character lists, this array marks the starts of the matching substrings in y.

'co' E. 'cocoa' 1 0 1 0 0

**Locating common values**: *Equal*

*Equal* (dyadic `=`) yields the Boolean result of comparing x and y--atom by atom, not larger aggregations. Either or both of x and y may be an atom, to be compared with each atom within the other.

] z=: i.5 0 1 2 3 4 3 = z 0 0 0 1 0 z = z 1 1 1 1 1 z = |.z 0 0 1 0 0

## Selecting

**Copying heads or tails**: *Take*

*Take* (dyadic `{.`) copies x head items from y--or (|x) tail items, when x is negative.

*Head* (`{.`) and *Tail* (`{:`) are convenient monadic equivalents for (`1{.`) and (`_1{.`) .

2 {. 'abcde' ab _2 {. 'abcde' de ] x=: 4 5 $ 65 }. a. NB. Reshaping a portion of Alphabet ABCDE FGHIJ KLMNO PQRST _2 {. x NB. Selecting rows KLMNO PQRST

**Discarding heads or tails**: *Drop*

*Drop* (dyadic `}.`) ignores x head items of y, and copies the rest of y. If x is negative, (`|x`) tail items are ignored.

*Behead* (`}.`) and *Curtail* (`}:`) are convenient monadic equivalents for (`1}.`) and (`_1}.`) .

2 }. 'abcde' cde _2 }. 'abcde' abc ] x=: 4 5 $ 65 }. a. NB. Reshaping a portion of Alphabet ABCDE FGHIJ KLMNO PQRST _2 }. x ABCDE FGHIJ

**Selecting from specified positions**: *From*

*From* (dyadic `{`) copies from array y those items with indices in x, in the same order. Negative values in x signify counting back from the end of the array, which is item number _1 .

This corresponds to indexing ("subscripting") an array in other computer languages. To *replace* the item at position x in y, see: *Amend* (`}`).

z=: 'abcde' 1 { z b 1 _1 { z be 2 4 { z ce

**Selecting within nested boxes**: *Fetch*

*Fetch* (dyadic `{::`) returns a list of contents from boxes in a boxed noun y . Each box in *path* list x contains boxed indices, each set selecting from successively lower levels of y.

Each sub-path of x selects within the target value(s) selected by its predecessor, generating a "tree" of boxed selections. If x points to a single box, the result is only the contents of that box.

] y =. 1 2 ; 3 4 ; 5 6 7 +---+---+-----+ |1 2|3 4|5 6 7| +---+---+-----+ 1 {:: y NB. Path x points to a single box 3 4 ] y=: 5!:2 <'boxxopen' NB. Internal representation of a utility verb +-+--+--------------+ |<|^:|+--+-+-------+| | | ||L.|<|+-+-+-+|| | | || | ||*|@|#||| | | || | |+-+-+-+|| | | |+--+-+-------+| +-+--+--------------+ 2 {:: y NB. Path x selects a single box, then opens it +--+-+-------+ |L.|<|+-+-+-+| | | ||*|@|#|| | | |+-+-+-+| +--+-+-------+ (2;0) {:: y NB. Deeper selections L. (2;2) {:: y +-+-+-+ |*|@|#| +-+-+-+ (2;2;1) {:: y NB. Down to lowest level (leaf of "tree") @ (0 ,: 1) {:: y NB. Two "parallel" selections (via Laminated indices) < ^: NB. Unboxed x and y specify simple consecutive indexings into y 5 6 {:: i. 10 10 NB. Fetching row 5, column 6 56 (<5 6) { i. 10 10 NB. Same effect using boxed index list and From 56

**Selecting unique values**: *Nub*

*Nub* (monadic `~.`) copies an array, omitting duplicate items--each item that matches a preceding item.

~. 'abracadabra' abrcd > 1 0 1 ; 0 1 1 ; 1 0 1 ; 0 0 1 NB. Creating a table 1 0 1 0 1 1 1 0 1 0 0 1 ~. > 1 0 1 ; 0 1 1 ; 1 0 1 ; 0 0 1 NB. Removing duplicate items (rows) 1 0 1 0 1 1 0 0 1

**Repeating items selectively**: *Copy*

*Copy* (dyadic `#`) creates a new array in which each item of y appears for the number of times specified by the corresponding integer value in x. x and y must have the same number of items. A Boolean left argument is often used as a selector, flagging particular items for extraction.

If x is an atom (a scalar value) then it applies to every item within y.

1 2 3 # 'abc' NB. Individual specifications abbccc 3 # 'abc' NB. Uniform repetition aaabbbccc

**Partitioning by words**: *Words*

*Words* (monadic `;:`) scans its character-string argument to identify individual J-words, and returns a list of those words, each enclosed in its own box. Since most words of natural language text could appear as value names in J, Words can usefully be applied in many text-processing areas. Do note, however, that all blank spaces will be lost, except in blank-separated numerical values or quoted strings.

NB. Separating into J-words ;: 'Words can be applied in 1 2 3 areas.' +-----+---+--+-------+--+--------+------+ │Words│can│be│applied│in│1 2 3│areas.│ +-----+---+--+-------+--+--------+------+ NB. Non-numeric blanks are ignored ;: 'Words can be applied in 1, 2, 3 areas.' +-----+---+--+-------+--+-+-+-+-+-+------+ │Words│can│be│applied│in│1│,│2│,│3│areas.│ +-----+---+--+-------+--+-+-+-+-+-+------+ NB. Displaying quoted value ] w123=: 'Words '' can '' be applied in 1, 2, 3 areas.' Words ' can ' be applied in 1, 2, 3 areas. NB. Quoted blanks survive intact ;: w123 +-----+-------+--+-------+--+-+-+-+-+-+------+ │Words│' can '│be│applied│in│1│,│2│,│3│areas.│ +-----+-------+--+-------+--+-+-+-+-+-+------+

**Partitioning by logical flags**: *Cut*

*Cut* (`;.`) is a conjunction creating one of seven different order-retaining partitioning adverbs, selected by a following integer parameter. Each uses a different mode of designating partition boundaries. Each partitioned subset is then processed separately by the adjacent verb.

**Definition:** An *interval of items* is a sequence of consecutive items of a noun, at whatever rank may be specified.

An item marking a boundary of an interval is called a *fret*, as are position markers on some stringed instruments. The ends of each interval are designated by a fret or by an edge of the array).

A Cut-produced adverb treats `y` as partitioned into a sequence of intervals, applying `u` individually to each interval, and combining those results into an array.

The seven meaningful selectors for Cut are 0 1 _1 2 _2 3 _3 . Selectors 1 and _1 use fret positions to mark the beginning item of each interval; 2 and _2 use frets to mark their ending items. The negative selectors cause the fret-positioned values to be dropped from their intervals.

**Case: u ;.1 y**,

*Self-intervals*

In ` u ;.1 y ` the delimiting frets are embedded in the data: those items of `y` that match its *head* item. As `y` is copied, it is split into intervals by starting a new interval with each item of `y` that matches the delimiter. Since the first item of `y` starts the first interval, each item of `y` will be in exactly one interval.

NB. The head item is 'a', so each 'a' starts a new interval. <;. 1 'a man, a plan, a canal: panama' NB. Boxing each interval +---+----+----+----+---+--+-----+--+--+-+ |a m|an, |a pl|an, |a c|an|al: p|an|am|a| +---+----+----+----+---+--+-----+--+--+-+ <;. 1 ] 3 1 4 1 5 9 2 6 5 3 5 3 2 3 8 NB. ''Right''separates numerics +-----------------+---+---+---+ |3 1 4 1 5 9 2 6 5|3 5|3 2|3 8| +-----------------+---+---+---+ +/;. (1) 3 1 4 1 5 9 2 6 5 3 5 3 2 3 8 NB. Summing within intervals 36 8 5 11

**In case: u ;.2 y**, embedded fret values mark interval beginnings, but match the

*tail*item, so that some head items could be omitted.

*Other monadic options* include applying u after full reversal or to maximal sub-cubes.

*Dyadic options* use a left argument of boolean values, to specify fret positions by its 1's, or of index ranges, to select a single sub-array or a regular tiling.

**Partitioning by key values**: *Key*

*Key* (`/.`) is an adverb, applied in (x u/. y), to extract items from x into partitions of identical items, not necessarily consecutive. u is then applied within each subset of y corresponding to a partition of x. Arguments x and y must have the same number of items.

Note: Noun x is used only for the partitioning, and is not an argument to operand u. Each item of x is a *key* for the corresponding item of y, and u is applied to each set of items of y with equal keys, in their original order.

y=: 'AbcDeFGhijk' ] x=: y e. 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' NB. Flagging uppercase 1 0 0 1 0 1 1 0 0 0 0 x ]/. y NB. Returning laminated values (with any needed fill) ADFG bcehijk x </. y NB. Returning list of separately boxed collections +----+-------+ |ADFG|bcehijk| +----+-------+

## Combining (specified sub-arrays)

**Applying in parallel**: *Plus*

*Plus* (dyadic `+`) adds corresponding atoms of two numeric nouns, x and y. Either or both of x and y may be an atom, to be added to each atom within the other.

**Note:** This is the prototypical verb having default rank 0 0, in common with all other fundamental arithmetic and logical operations.

**Note:** A verb applied in parallel may operate serially within each of the sub-array components involved.

**Note:** When x and y are of different shapes, a *Rank* adverb may be able to direct how to match up an atom of either argument with a corresponding subset of the other.

2 + 3 5 x=: 5 y=: 2 3 4 x + y 7 8 9 y + x 7 8 9

**Applying to subsets**: *Rank*

*Rank* (`"`) is a conjunction such that (u"n y) applies the verb u in turn to each n-dimensional cell ("n-cell") of an array y. u"n creates a transitory verb whose application rank is n, collecting the varied n-cell results into a single array. Specifying a rank of (m, n) causes u to be applied between m-cells of x and n-cells of y.

*Rank* is the *most-often-used modifier* in J. It encapsulates and directs what is termed *simple looping* in many programming languages. A thorough discussion can be found at Rank.

The *for.*, *while.*, and *whilst.* control words in J permit expanded description and viewing of repeated actions, including more complicated specifications.

] y=: i. 2 3 0 1 2 3 4 5 u=: < NB. u designates the primitive verb: Box u y NB. Applying Box (<tt><</tt>) to the whole of y +-----+ |0 1 2| |3 4 5| +-----+ u"1 y NB. Applying Box (<) to each 1-cell, i.e. each row (list) of y +-----+-----+ |0 1 2|3 4 5| +-----+-----+ u"0 y NB. Applying Box (<tt><</tt>) to each 0-cell, i.e. each atom of y +-+-+-+ |0|1|2| +-+-+-+ |3|4|5| +-+-+-+

**Applying tensorially**: *Table*

*Table* (`/`) is an adverb that makes (x u/ y) return a table having entries (a u b) from pairs of every a in x and every b in y--their "tensor product"--*provided that the dyadic verb u has Rank 0 0.*

For other ranks of the verb, u is applied between each operand cell of x (whose rank is given by the left rank of u) and the entire y. The results of these executions are collected into the final result. **Note** that verb u is applied to *cells*, which may not happen to be items or atoms.

] z=: >: i.6 1 2 3 4 5 6 z */ z NB. Showing multiplication table 1 2 3 4 5 6 2 4 6 8 10 12 3 6 9 12 15 18 4 8 12 16 20 24 5 10 15 20 25 30 6 12 18 24 30 36 NB. To demonstrate that a matrix is orthonormal, take the dot product of NB. each of its columns with each other. After transposing the matrix to NB. a list of its columns (as rows), the rank-1 dot-product verb creates NB. a table of their combinations, which should be (nearly) an Identity. dotproduct =: +/ @: *"1 ] mtx=: 3 3 $ 0 _0.8 _0.6 0.8 _0.36 0.48 0.6 0.48 _0.64 0 _0.8 _0.6 0.8 _0.36 0.48 0.6 0.48 _0.64 (|: mtx) dotproduct/ (|: mtx) NB. Column against column: looks orthonormal 1 0 0 0 1 5.55112e_17 0 5.55112e_17 1

** Applying serially**: *Insert*

*Insert* (`/`) is an adverb directing (u/ y) to apply (dyadic) u between successive items of y, returning a single summarizing result.

**Note:** A verb applied serially may operate in parallel between the sub-array components involved.

] z=: >: i.6 1 2 3 4 5 6 +/z NB. Equivalent to (1+2+3+4+5+6) 21

**Cumulating partials**: *Prefix*

*Prefix* (`\`) is an adverb causing (u\ y) to apply dyadic u between successive items of y, returning the results of serial application within successive prefixes (e.g. "running sums").

] z=: >: i.6 1 2 3 4 5 6 +\z NB. Equivalent to (1),(1+2),(1+2+3),(1+2+3+4),(1+2+3+4+5),(1+2+3+4+5+6) 1 3 6 10 15 21