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 0 (*-)2 NB. 2 * -2 _4 (**:)3 NB. * is times and *: is square 27
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 (%+/)i.5 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 7 avg 1 2 4 8 16 6.2 avg 2 ^ i. 5 6.2
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 [*>: tri +--+-------+--------+ |[:|+-+-+-+|+-+-+--+| | ||%|&|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.
2007-05-14 at 14:47:13
No comment.
2007-05-21 at 13:43:12
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).
2007-05-21 at 17:09:59
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.
2007-05-21 at 17:41:00
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.
2011-04-25 at 01:48:33
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.