J: Working with Henry Rich's Example
Today I’ll report on experience working part way through one piece of Henry Rich’s J program for bowling. Understanding dawns slowly.
We have referred to Rich’s example before. Here it is in its entirety:
NB. Index of each ball that starts a frame framex =: 10 {. 0 {~^:a:~ _1 _1 ,~ i.@# >:@:+ 10&~: NB. Score for each ball, assuming that ball starts a frame scoreifframe =: 3 +^:(9<])`+/@|.\ ,&0 NB. Pick the balls that actually start frames & add em up gamescore =: [: +/ framex { scoreifframe
I thought it would be good to try to learn from a master, so I started working through this example. I started just with the framex function, that allegedly returns a list of the starting indexes of each frame. I began by typing “framex” into J, so that it would print out a boxed parsing of the line:
This appears to me to be the parsed form of the object framex, which is a verb. The main thing I get from it is that patch in the innermost rightmost box:
i.@# >:@:+ 10&~:
I note that J has parsed out three separate “verbs” here. And I remember that three “isolated” verbs are taken as a “fork”. I see no argument on the left, so I’m guessing the fork is to be interpreted thus:
(f g h) y –> (f y) g (h y)
I’m not certain of this. With J I find that I am still flying blind, and that my assumptions are often blown away after I go deeply into things. I’m not sure if this will be another of those cases. (Spoiler: it isn’t. I appear to be on the right track this time.)
So let’s look at the three bits one at a time:
10&~:
~: is “not equal”. & ties things together, in particular it is used to bind constants into verbs. So I conclude that 10&~: is a new verb, “not equal to ten”.
And sure enough,
10&~: 1 10 2 10 3 10 4 1 0 1 0 1 0 1
We get a one (true) wherever the input here isn’t ten. Woot! We are totally on a roll. What about the function on the other side of the fork, namely i.@# ?
The # verb is “tally”, number of items. The @ means “atop”, with a definition of
f@g y –> f g y
I take that to mean that the @ is used (somehow) to ensure that we apply tally, then apply i. to the result of that. And i. is the “integers” verb, that given i.3 returns 0 1 2, the integers up to 3.
So if I’m correct, and frankly I wasn’t as sure then as I am acting now, this bit will return the integers from zero up to the number of rolls in the example we have. I have a game I made up that goes like this:
4 5 4 5 10 4 5 4 5 4 5 4 5 10 4 5 4 5
and when I apply i.@# to that, I get
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
OK, well that seems to be right … but I have doubts. The reason is that this is such a butt-simple thing to be wanting. Why would this competent J programmer be going to this much trouble to get the integers from 0 through 17?
When I was working on this, I spent a bunch of time trying other things to see whether there was some more reasonable-looking result. I never found one, so pressed on. I saved my sample game as “rolls”, and this result as “seq” just to be able to refer to them. And I’ll call the 1 1 1 0 thing “notTens”.
Where Am I?
By this point, I’m carrying a big load of uncertainty: I’m not entirely sure why we want so far to get the numbers 0-17, so I’m not entirely sure that’s what the code really does. I’m pretty sure about the 1111 0 111 thing: that looks useful.
This is painful. When I’m working in a more conventional language, doing TDD, I am always very certain what my program does. Now, of course, in a legacy app like Rich’s bowling scoring, I would be uncertain in any language … but in a conventional language I would at least know what the statements do.
J is designed and built such that without really understanding verbs and adverbs and conjunctions and hooks and forks and who knows what all … I can’t be sure I understand any of it.
Moving Right Along
Despite the stress of uncertainty, I decided to press on. On the assumption that the triad above is a fork, it is now time to look into what >:@:+ means. I assume it is not some kind of smiley meaning something like totem pole with vomiting head on top.
I know what + means: it’s add. Since we will have (according to the fork theory)
seq >:@:+ notTens
the rightmost operator just has to be dyadic (takes two args). Looking up the others, I find that >: means “increment” and @: means “Atop”, defined as “just like @ except of infinite rank”. The examples aren’t much more help.
I’ll spare you most of my anguish. Probably because of my general uncertainty about all this, and because of how tired I therefore was, I spent a lot of time playing with this operator to figure out, not just what result it gave, but what it means.
When we apply the operation we get this:
seq >:@:+ notTens 2 3 4 5 5 7 8 9 10 11 12 13 14 14 16 17 18 19
Now this confused me at two levels. First, I wasn’t sure what it was good for. Second, I couldn’t see how it was working. If we look at it like grade school arithmetic, we see this:
1 1 1 1 0 1 1 1 1 1 1 1 1 0 1 1 1 1 NB. "x" >:@:+ 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 NB. "y" = 2 3 4 5 5 7 8 9 10 11 12 13 14 14 16 17 18 19
Now that is sort of evocative. We know that we are trying to get the indexes of the starting rolls of frames out of this thing, and it is rather interesting how this expression holds steady under a zero, then picks up +2 later. (Note the 5 5 7 and the 14 14 16.)
However, I couldn’t see how increment and plus worked out to create those numbers. Probably if you look at them now, it will be obvious. (I kind of hope not but suspect that it will be.) Looking at it now, it seems clear that the answer in each position is x + y + 1.
I was confused enough, and uncertain enough, and frustrated enough that I did not see that. And because I had (and still have) little idea what this sequence is good for, the uncertainty blinded me to the obvious.
The >:@:+ could be read, according to the vocabulary, as “increment atop plus”. That might have been enough for someone whose brain was working. I wrote a long email to Tracy Harms (thanks!) explaining where I was, and he came back with some explanation and the notion that calling it “increment after plus” made more sense (at least in this case).
Yes. the operation is increment after plus, so the result is what a C kind of guy would call (x + y)++ or x + y + 1.
Now What?
By this time, I was really whipped. Even after I got updated by Tracy, I feel kind of burned out on this path. I do see a couple of things in the remaining bits. Recall the definition:
framex =: 10 {. 0 {~^:a:~ _1 _1 ,~ i.@# >:@:+ 10&~:
I recognize the _1 _1 , ~ bit! The ~ is an appendage, probably an adverb, that means reverse these arguments. So while 5 - 1 is 4, 5 -~ 1 is -4, or _4 in J speak, because the arguments are reversed. So that little snippet is going to append two negative ones onto the end of our list. They look like EOF markers to me. So I anticipate, with some confidence, that the next bits will be doing something to the result until it hits those _1 values.
A quick scan of the rest, even looking at the parse from the boxes above, is not helpful. The a: is “the boxed empty list”. I don’t understand boxes yet, so that’s a quick “huh?” The ^: is called “power” and seems to be some kind of iteration verb. I don’t understand that either. The ~ on the right could be a reverse. I suppose the one on the left could be as well. The { is called “catalogue” when it’s monadic, and “From” when it is dyadic. In its “From” form, x { y takes the x-th item from y. I suspect this is “From”. I suspect it is some kind of iterative processing of the list, based on “power” meaning something like repetition, and on the _1 flags at the end.
Beyond that, no clue. So that’s where I’ll probably need to look next. I tried, quickly, to type in some subsets of the expression. The whole expression does provide the avowed list of frame starts. Most of the subsets weren’t even accepted as valid expressions.
So I got some learnin ta do.
Status of the Project
This is really daunting. It’s clear from looking at J that the style of Henry Rich’s example is pretty good J, so learning how to do it that way seems like a good idea. On the other hand, it is taking me many minutes to figure out each tiny step. I like to think that I’m fairly smart about programming, and I haven’t been this confused for this long, for many years.
I’m not sure what I’d do were I not writing this series of little articles. I might just quietly turn away and try something easier, like string theory. Certainly I don’t want to lose face here in front of both of my readers, giving up on something.
It could be argued that the benefit of learning J will never be accrued in my lifetime, and that stopping a bad idea is a good idea. I may resort to that soon.
It is also the case that I’m stubborn. Combining that with the fact that I imagine myself to be pretty good at programming, I am not inclined to give up just yet.
So, what’s next? I’m not sure. We’ll see … thanks for tuning in!