Learning J – Part IV


Please see Learning J Part I, Part II, and Part III.

Strings of verbs that are not parseable with the usual dyadic–monadic machinery are called trains. (%+/) is a train of two verbs; the first verb is % (division), the second is +/ (the verb + modified by the adverb / to produce the sum-list verb).

A train of two verbs f g is called a hook (or bident, but that isn’t used as much). When used monadically (f g) x is the same as x f g x. Notice the repetition of the x operand.

   (+-)7  NB. 7 - 7 = 0
   (*-)2  NB. 2 * -2
   (**:)3 NB. * is times and *: is square

So (%+/) n is the same as n % +/ n which if n is a list then this rescales the list so that the sum of the result is 1:

   i. 5
0 1 2 3 4
0 0.1 0.2 0.3 0.4

Dyadic hooks are boring, x (f g) y is the same as x f g y.

A 3-element train, f g h, is called a fork (or, again less often, trident). The monadic case (f g h) y is the same as (f y) g (h y), and the dyadic case x (f g h) y is the same as (x f y) g (x h y).

This is all tolerably well explained in Appendix F of the J dictionary.

The mnemonic that I use for remembering the difference between monadic and dyadic tridents is that the monadic case is just the same as the dyadic case but with x removed. Dyadic: (x f y) g (x h y); Monadic: (f y) g (h y).

Recall the parsing rules of Appendix E, and observe that larger sequences of verbs get decomposed into hooks and forks. b c d e is b (c d e); that is, the hook of b and the fork c d e. a b c d e is a fork of a fork: a b (c d e).

The classic pedagogical fork computes the average of a list:

   avg =: +/ % #
   avg 6 7 8
   avg 1 2 4 8 16
   avg 2 ^ i. 5

Observe that the repetition of operands is useful and can avoid temporaries. i.11 */ i.11 produces a multiplication table. We can use the fact that a bident duplicates its operand: (*/ g) i. 11 will do if we can find a monadic g that does nothing. Both [ and ] are monadic identities. So we can get the same multiplication table with (*/]) i. 11. As it happens this simple duplication is so useful that there’s an adverb, ~ (twiddles), to do it. u~ y is y u y. So */~ i. 11 also produces the same table.

Suppose we wanted to compute triangular numbers. tri(n) = (n×(n+1))/2. Perhaps we would like to use J to solve Gauss’s little school problem. Note that n×(n+1) can be computed with a bident: (*>:) (>: is the successor function). Now all we have to do is halve the answer. The currying conjunction & comes in handy. The monadic %&2 halves its operand; %&2 y is the same as y%2. We can use @ to compose these two:

   tri =: %&2 @ (*>:)
   tri i.10
0 1 3 6 10 15 21 28 36 45

In fact the brackets aren’t necessary. We can get rid of the brackets around the bident by using the monadic identity, [, in a trident:

tri =: %&2 @ [*>:

It’s a little shorter, but I’m not convinced that it’s any neater.

I tried this form, and it works, but not for the reasons that I thought it did. The spacing I’ve used above suggests I have a trident on the right, a curried divide operator on the left, and I’ve joined them with @. We can use J to see how it’s actually been parsed:

   %&2 @ [*>:
||+-+-+-+|@|[|| |  |
|||%|&|2|| | || |  |
||+-+-+-+| | || |  |
|+-------+-+-+| |  |

The kinda scary looking boxes are just another way to write brackets (in this case). So %&2 @ [*>: turns out to be parsed as ((%&2)@[)*>:. Lesson: be careful. This is actually computing (n/2)×(n+1); of course this is mathematically the same as (n×(n+1))/2 but the latter can be done in integer arithmetic whereas the former requires fractions. Good job halving is an exact operation in IEEE arithmetic.

The reason %&2@[*>: gets parsed as it does is that the trident reduction cannot take place if there is a conjunction to the left of the potential trident. When the stack has the four terms @ [ * >: on it, @ is a conjunction so [ * >: will not be reduced to a trident. The conjunctions get reduced first.

Conjunctions get reduced left to right. %&2@[ is (%&2)@[. Referring to the parsing table again we see that’s because a conjunction won’t be reduced if there is a conjunction immediately to its left.

Since [ is monadic identity, the [ in %&2@[ is not necessary. We can just use %&2 instead: %&2*>:. It also turns out that dividing by 2 is sufficiently useful that there’s a primitive to do it: -:. So we can use tri =: -:*>:, which is just a single trident.

Cap, spelt [:, is a magic verb used in tridents. [: g h is the same as f g h but without the entire f branch. So x ([: g h) y is g (x h y), and ([: g h) y is g h y.

The last form of cap is found in our original triangle formula that used @: tri =: %&2 @ (*>:). We can remove the @ conjunction and replace it with a cap instead:

   tri =. [: %&2 (*>:)

And this time we can replace the bracketed bident on the right with a trident that uses [:

   tri =. [: %&2 [*>:
|  ||%|&|2|||[|*|>:||
|  |+-+-+-+|+-+-+--+|

This does get parsed how we (or at least I) expect, with [ * >: on the right being reduced to a trident.

Using -: and, for amusement, swapping ] for [ we get:

   tri =: [:-:]*>:

To be honest this seems like an exercise in fruitless manipulation, but I’m sure I’ll be finding all sorts of witty things we can do with forks and hooks.

5 Responses to “Learning J – Part IV”

  1. rk Says:

    No comment.

  2. YAJer Says:

    You can configure J to display trains (and other derived functions) in different ways.

    If you are using a windowed instance of J, you can use the Edit->Configure menu option. If you are using the command line, you can use 9!:3, with the default being 9!:3]2 and my personal favorite being 9!:3]5 (but for learning, I would probably use something like 9!:3]6 4 5 which, ironically, you can’t quite select with the GUI).

  3. drj11 Says:

    Thanks for the tip. I have to say I find the tree presentation to be butt ugly. I like the idea of showing both the parenthesised and the linear representation with 6 5.

    The «9!:3]6 4 5» is a witty use of what presumably becomes an idomatic bident.

    I’m used to the boxes now. And it feels closer to the Truth.

  4. YAJer Says:

    Yeah, boxes are closer to the Truth. That said, boxes, linear and parenthesised are all complete — the mapping from J to those forms and back is 1:1. That said, only linear (and parenthesised) map 1:1 though the console. You can’t throw the boxes at a console session and expect to get anything useful — even if they do perhaps provide deeper insight into how J represents things internally.

    Anyways, the nice thing about personal taste is that you can have yours without any work on my part.

  5. icankillufoo Says:

    I read all of the Parts, and now my head hurts.
    Thanks tho. I now understand more of the values and the order to place them in.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: