Vocabulary/NounExplicitDefinition
Defining a noun as an explicit entity using (:)
A noun is usually created as a noun phrase, i.e. a phrase that evaluates to a noun.
Typically the noun thus created is straightaway assigned to a name in order to create what other programming languages call a (named) variable.
Example:
] z=: 'alpha',LF,'bravo',LF,'charlie',LF alpha bravo charlie NB. Note how that trailing LF gives a trailing blank line
LF 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'
Defining a LF-separated string
But you can also create the same noun like this:
z=: noun define alpha bravo charlie ) assert z -: 'alpha',LF,'bravo',LF,'charlie',LF
noun define is equivalent to the phrase: 0 : 0
This is useful when you need to represent a table z inside a script, in the form in which you'd best like to visualize it.
If you define z in the above way, you always get a final linefeed character (LF). Sometimes this is inconvenient because some algorithms may take this to represent a final empty row.
You can drop the final LF like this:
z=: }: noun define alpha bravo charlie )
However in general it is wise to retain it. Some utility verbs tolerate its (possible) presence. Additionally if you think of LF as being a line terminator, not a line separator, then every line is correctly terminated as things stand. Also the number of LF bytes is equal to the number of lines, so you can count lines by counting the LF characters
+/z=LF
Defining a list of boxed strings
At first sight noun define only lets you define a noun which is a LF-separated string, i.e. a list of bytes which is not actually a table, but only looks like one when displayed in the J session because it happens to contain linefeed characters (LF).
However you can build any type of noun by variations on the general principle
z=: convert noun define ... )
with a suitable choice of the verb: convert.
To build a list of boxed strings, the choice is simply cutopen in place of convert
z=: cutopen noun define alpha bravo charlie delta echo foxtrot golf ) z +-----------+-------+------------------+----+ |alpha bravo|charlie|delta echo foxtrot|golf| +-----------+-------+------------------+----+
cutopen 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'
Instead of cutopen, you sometimes see Cut (;.) used with appropriate operands, which gives the same result
z=: <;._2 noun define alpha bravo charlie delta echo foxtrot golf ) z +-----------+-------+------------------+----+ |alpha bravo|charlie|delta echo foxtrot|golf| +-----------+-------+------------------+----+ )
Defining a table of characters
If you apply Open (>) to a list of boxed strings, the result is a table of characters. So this is an easy modification of the foregoing example
z=: > cutopen noun define alpha bravo charlie delta echo foxtrot golf ) $ z 4 18 z alpha bravo charlie delta echo foxtrot golf
Defining a table of numbers
As stated above, with a suitable choice of the verb convert you can build a noun of any type and rank. For example, a table of numbers.
A J beginner might think that the only sensible way to define a 2-by-3 table of numbers inside a script is by reshaping a list of numbers specified as a constant like this:
n=: 2 3 $ 100 101 102 200 201 202
But this has the disadvantage of being hard to visualize, especially for large tables.
Another way is to build up the table n row-by-row, like this:
n=: 0 3 $ 0 n=: n , 100 101 102 n=: n , 200 201 202
which does at least show the layout of n. But it has the disadvantage of entailing a separate execution for each line. This is not in the spirit of J, which lets you do better than that.
Let's write down the table n in the form we'd prefer to visualize it, viz directly as a 2-by-3 table, but within the definition of a LF-separated string, z
z=: noun define 100 101 102 200 201 202 )
Now convert it in stages to any shape and type of n you like
]ztable=: >cutopen z NB. converts "lines" to rows in a table of rank 2 100 101 102 200 201 202 $ztable NB. like z, ztable is (bytes) 2 11 $ n=: ". ztable NB. but n is (numbers) 2 3 -n _100 _101 _102 _200 _201 _202
You can do all this in one sentence — the very sentence which assigns the newly-built noun to the name: n
n=: ". >cutopen noun define 100 101 102 200 201 202 )
cutopen, noun and define are
- 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'
Building the state transition table of a sequential machine
We turn now to building a brick, i.e. a rank 3 array, which at first sight doesn't lend itself to a variation on
z=: convert noun define ... )
But it does benefit from being visualized and maintained in table form.
Consider the primitive: Sequential Machine (;:).
The dyadic phrase: x ;: y splits string 'y' into boxed words according to a syntax defined by the left-hand argument x.
The monadic phrase: ;: y is the same as: x ;: y but with a special built-in default value of x which implements a sequential machine to treat y as J code, and split it into words accordingly.
The chief and most critical part of this default value of x is the state transition table, defined in JDic:d332 like this:
sj=: _2]\"1 }.".;._2 noun define ' X S A N B 9 D C Q ']0 1 1 0 0 2 1 3 1 2 1 6 1 1 1 1 1 7 1 NB. 0 space 1 2 0 3 2 2 3 2 2 2 6 2 1 0 1 0 7 2 NB. 1 other 1 2 0 3 2 0 2 0 2 0 2 0 1 0 1 0 7 2 NB. 2 alp/num 1 2 0 3 2 0 2 0 4 0 2 0 1 0 1 0 7 2 NB. 3 N 1 2 0 3 2 0 2 0 2 0 2 0 5 0 1 0 7 2 NB. 4 NB 9 0 9 0 9 0 9 0 9 0 9 0 1 0 1 0 9 0 NB. 5 NB. 1 4 0 5 6 0 6 0 6 0 6 0 6 0 1 0 7 4 NB. 6 num 7 0 7 0 7 0 7 0 7 0 7 0 7 0 7 0 8 0 NB. 7 ' 1 2 0 3 2 2 3 2 2 2 6 2 1 2 1 2 7 0 NB. 8 '' 9 0 9 0 9 0 9 0 9 0 9 0 9 0 9 0 9 0 NB. 9 comment )
This shows one way of handling row and column labels in a table of numbers. It also shows how to make a rank-3 table.
A key point about the state transition table is that it must be rank-3, the last dimension consisting of pairs of numbers. Our technique primarily yields a rank-2 array of numbers, which then needs to be reshaped.
However there is a simple trick to temporarily eliminate the last dimension (provided it consists just of number pairs):
- Combine each pair into a single (complex) number
- Drop the (non-numeric) labels before converting the bytes to numbers by the more straightforward technique of using (}.)
- Expand the complex numbers into pairs of integers using (+.) to restore the 3rd dimension.
This lets us simplify the table definition by adapting our earlier use of: >cutopen
sk=: +. ". (1 _11) }. >cutopen (0 : 0) X S A N B 9 D C Q 1j1 0j0 2j1 3j1 2j1 6j1 1j1 1j1 7j1 0 space 1j2 0j3 2j2 3j2 2j2 6j2 1j0 1j0 7j2 1 other 1j2 0j3 2j0 2j0 2j0 2j0 1j0 1j0 7j2 2 alp/num 1j2 0j3 2j0 2j0 4j0 2j0 1j0 1j0 7j2 3 N 1j2 0j3 2j0 2j0 2j0 2j0 5j0 1j0 7j2 4 NB 9j0 9j0 9j0 9j0 9j0 9j0 1j0 1j0 9j0 5 NB. 1j4 0j5 6j0 6j0 6j0 6j0 6j0 1j0 7j4 6 num 7j0 7j0 7j0 7j0 7j0 7j0 7j0 7j0 8j0 7 ' 1j2 0j3 2j2 3j2 2j2 6j2 1j2 1j2 7j0 8 '' 9j0 9j0 9j0 9j0 9j0 9j0 9j0 9j0 9j0 9 comment ) sk -: sj 1