<< >> Contents Help

# 41. Common Mistakes

Mechanics

Watch out for Adjacent Numbers

>:"0 1{y

fails because the 0 and the 1 are considered part of the same list. Use >:"0 (1{y) or >:"0 ] 1{y .

Names in Sequence Do Not Form a List

0 1 is a 2-element list, but 0 y is an error even if y has the value 1 . Use 0,y .

Remember Right-to-Left Evaluation When You Use J as a Desk Calculator

J makes a great desk calculator, but you have to remember to translate from mathematical notation to J correctly. 5 - 2 + 1 is 2, not 4 .

How to Remember the Monads {. {: }. }:

Remember that { means take (x takes from y), so } must be drop. The single-dot means beginning, and the double-dot means end. So, }. means 'drop the first item'.

How to Remember #. and #:

The single-dot produces a single (atomic) result; the multiple-dot produces a list.

Remember the Operand Order in e. i. and |

The normal J convention is that a dyad's y operand is the one that is more 'data-like' and its x operand is more 'control-like'. Thus, in x i. y, x is a table and y is one or more values to be looked up in the table. By this convention, x e. y is backwards: y is the table and x is the values.

Similarly, x | y seems backwards from x % y .

Leave a Space Before : When Used Alone

When you use : or . as a conjunction, you must remember to leave a space before the : or . so it will not be interpreted as an inflection. The following are all errors: 3:0, (+/ % #):* , and +/.* .

Use =: for Assignments Within Scripts

Code that runs perfectly well from the keyboard may not work if you put it into a script (.ijs) file. The problem is usually that you have used =. for some assignments. Entered from the keyboard, =. gives a public assignment, but to get the same effect in a script, you need to use =: .

Pasting Into an .ijx Window Does Not Execute

Remember that when you paste a block of text into an .ijx window, that text shows up in the window but it is not executed. To execute the text, you need to select it and then use Run|Selection.

Don't Mix elseif. and else. in the Same Structure

The control structure if./do./elseif./do./else./end. is not legal. Once you have used an elseif. you are not allowed to code else.; use elseif. do. instead of else. (the omitted condition always tests true).

Programming Errors

Remember the Asymmetry of Dyad ;

x ; y always boxes x, but it boxes y only if y is unboxed. This gives you what you want when the operands are unboxed:

1 ; 2 ; 3

+-+-+-+

|1|2|3|

+-+-+-+

But when the operands are boxed, you may be surprised at the result:

(<1) ; (<2) ; (<3)

+---+---+-+

|+-+|+-+|3|

||1|||2|| |

|+-+|+-+| |

+---+---+-+

To have the last operand boxed, you should box it explicitly:

(<1) ; (<2) ;< (<3)

+---+---+---+

|+-+|+-+|+-+|

||1|||2|||3||

|+-+|+-+|+-+|

+---+---+---+

Don't Give Two Operands to a Monadic Verb

When you start writing long tacit programs, you are likely to have trouble keeping track of whether a verb is being executed monadically or dyadically. Suppose that x is a set of observations and y is a set of weights, and you want to weight each observation and divide by the total weight. You might try

x (* % +/) y

but that isn't right—the sum of the weights is +/ y and this is going to execute x +/ y . What you meant was

x (* % +/@:]) y

Some rules to remember: a train comprising an odd number of verbs is a fork, which can be invoked monadically or dyadically. The first, third, etc.… verbs, including the last, are all executed with the same valence as the fork itself, and their operands are all the same, namely the operands of the fork itself. The second, fourth, etc.… verbs are all executed dyadically, with operands that are results of other verbs in the train.

A train comprising an even number of verbs is a hook. The first verb in the hook is always executed dyadically; the rest, taken as a train, are executed monadically on the y operand of the hook.

If any part of your train requires simultaneous access to the x and y operands of the train, you must make the train a fork rather than a hook.

Use @: Unless @ Is Necessary

u@:v has infinite rank, while u@v has the rank of v . If you don't see what difference this makes, you should drop what you are doing and read the chapter on "Compound Verbs". For practical programming, you should be in the habit of using @: unless you need u to be executed on each individual result-cell of v, in which case you may use @ . The most common uses of @ are u@> to execute u on the contents of each box in a list, and <@v to box each individual result-cell of v .

Put Parentheses Around Compounds Inside Other Compounds

A modifier is greedy about what it takes for its left operand, hoovering up everything until it hits a left parenthesis or unmodified verb. For example, if you want to add 2 to y and then double the result,

+: @: 2&+ y

is going to disappoint you, because it is executed as (+:@:2)&+ y which isn't even legal. You meant + @: (2&+) . Be liberal in your use of parentheses inside compounds. You may omit the parentheses around the leftmost compound—another way to write the above would have been 2&* @: (2&+)—but you won't regret putting parentheses around all compounds, especially when you go to change your code.

I find it easy to forget the parentheses when one of the verbs is something like +/ that I use so much that I think of it as a primitive. When something like >: @: +/ fails I am brought back to reality and I remember to write >: @: (+/) .

A Verb Is Always Executed, Even If Its Operand is Empty

J's primitives are defined to produce reasonable results when given empty operands. You should do as well with the verbs you write. Remember that if a verb has an operand with no cells, the verb is still executed once, on a cell of fills. The chapter "Empty Operands" explains what happens.

Dyad -: Does Not Check the Type of Empty Operands

Be aware that getting a result of 1 from x -: y does not guarantee that x and y are equivalent. If they have the same shape and are empty, they are considered to match even if they have different types. Subsequent operations such as {. would reveal the fact that the values are different, even though they 'match'.

x u/ y Applies u to Cells of x

To get x u/ y right, remember that it applies u to cells of x and the entire y . The rank of the cells of x is given by the left rank of u; use u"n/ to set the cell-rank of x .

Modifiers That Refer To y. Have Monadic and Dyadic Valences

If your modifier contains x. or y., its text defines a verb which is executed when its noun operands are known. This verb, like any explicit verb, can have both monadic and dyadic versions, separated by a line containing just a ':' character. If you want the modifier to have a dyadic form, you must code one (by default the verb will be monadic only).

Tacit Code Does Not Simply Replace a Name By Its Definition

It is easy to develop an incorrect mental picture of how tacit programs are executed. One common error is to think that names are replaced by their definitions before a sentence is executed, in other words that if you have

plus =: +

then a sentence

1 plus 2

is converted to 1 + 2 and then executed. This notion immediately leads to confusion when you encounter

mean =: +/ % #

and you expect

mean 1 2 3 4 5

to be executed like

+/ % # 1 2 3 4 5

which is not how it works. If you find yourself making this error, read the chapters on Tacit Programming to learn what really happens.

As a stopgap, you can imagine that each name's value is enclosed in parentheses before it is substituted. This still isn't exactly right but it gets you the right result in all situations you are likely to encounter. You would imagine that the sentence above is executed as

(+/ % #) 1 2 3 4 5

which gives the correct answer. You must realize that (+/ % #) is a fork, with its own rules for processing its operands.

<< >> Contents Help