No, really. This is hard. People ask me why I'm doing it. There are reasons ...

Thanks ...

I’m glad people are reading these articles, and I’m hoping one day they’ll turn out to be useful. The idea, as with Adventures in C#, was to give some insight into how I think about learning a new language or system, in the hopes that people would find it useful, or at least amusing. So if you’re out there … thanks!

What, and Why ...

People hear my plaintive tweets or read these articles and then ask me why I’m doing this if it is so painful. I’m starting to wonder, frankly, but not in a good way. J is unquestionably powerful, and in the hands of someone who knows it, at least some problems yield very interesting solutions. I’ve been interested in the occasional J comments that come by, from June Kim and more recently from Tracy Harms and others. They’re always so gung ho about J. So I thought I’d give it a go–how hard could it be?

It turns out it is bloody hard, at least for me, and I have reason to believe that I used to be quite intelligent, despite recent evidence to the contrary. How hard? Well, let’s talk about bowling scoring, since that’s my canonical app.

In, say, Ruby, the actual algorithm for scoring a list of bowling rolls requires, roughly:

  • integer data type
  • plus operation
  • compare for =
  • if {...} else if {...} else {...}
  • for ( frame=0; frame<10; frame++)
  • def / end and similar boilerplate

In a note yesterday, Tracy Harms included a list of the things he thinks one needs to know in order to begin getting J. This list is of course longer than the one above, since someone who could do bowling could hardly be said to “get” Ruby. It would be a start, however: there are a lot of programs you can write with just the stuff above.

Tracy’s list identified over 100 things that you need to know. Some of them are just simple operations: 2 + 2 results in 4. Of course simple operations work on lists and arrays in J so you get 2 3 + 1 2 yielding 3 5. Yum

But wait, there are modifiers like /. +/ 1 2 3 is the sum, 6. */ is the product (in this case also 6, isn’t that interesting).

So there is lots. And it seems that you can’t do much of anything without knowing way more.

Finally, the real issue is that the whole model is different. Conventional languages think about atoms, numbers, maybe strings, and they process collections reluctantly at best. J has notions of collection embedded deeply within its thinking. Using it to process things one at a time is almost a sin.

So it hurts, going into my head. Why do it? Because it’s so different that it seems to me the investment is likely to pay off, if only by building up muscle in my brain.

Progress So Far ...

Let’s take a look at my status as of now.

Arrgh. My status just deteriorated. I saved a “session” file before shutting down this morning, and if there is a way to restore it, I can’t find it. I can open it in a text editor, at the cost of lost boxes and such. Oh well.

First, some learnings. I learned that you can extract certain items from a list with the # verb:

   i.6
0 1 2 3 4 5
   1 0 1 0 1 0 # i.6
0 2 4

That could be handy, I’m supposing. And I learned or already knew how to find all the tens in a list of rolls:

   rolls =: 4 5 4 5 10 4 5 4 5 4 5 10 4 5 4 5 4 5
   rolls = 10
0 0 0 0 1 0 0 0 0 0 0 1 0 0 0 0 0 0
   (rolls = 10) # rolls
10 10

So that was nice. I began to think of a setup where each frame was represented by three integers … because every frame in bowling is the sum of three values:

  • Open: first roll + second roll + 0
  • Spare: first roll + second roll + third roll
  • Strike: first roll + second roll + third roll

I know that because I discovered it a time or two, while refactoring a procedural bowling game. I’m not sure if it will be useful for J, but since I don’t really know how to do this in J, I thought I’d push it.

So I began with the question of how I could transform something like

4 5 4 5 10 4 5

two opens, a strike, and another open, into

4 5 4 5 10 0 4 5

by inserting an extra zero in there. My thought was that I’d make a framing area and then fill in the bonus rolls separately somehow. This was just a start, at doing an insert. I couldn’t figure out how to do it, so I tweeted the problem. (Thank you, twitter, for having so much help available to me.)

Tracy wrote me a lovely long note showing how he derived this operation. It took him a fair number of trues to get it, which may be interesting to think about. Right now, we’ll think about what he did, because it really caught me unawares.

Remember that

1 1 1  0 0 # 1 2 3 4 5

would give us 1 2 3, and of course

1 1 1 1 1  # 1 2 3 4 5

would give us the whole thing back. Tracy wrote a moderately complex expression that resolved down to something like

1 1 1j1 1 1 # 1 2 3 4 5

That 1j1 in the middle of the selector list? That’s J talk for 1 + 1i. It’s a complex number!!! Wha???

OK. Reading the description of # more carefully, we learn first, that

3 1 1 # 1 2 3

would give us

1 1 1 2 3

If the integer isn’t 1, you get however many it represents, three in this case.

Reading on you find that if there is an imaginary part on the number, the # operation will insert that many default values. So that

1 1 1j1 1 1 # 1 2 3 4 5

will give us

1 2 3 0 4 5

by inserting the zero. Naturally you can insert more than one. And also you can change what the default is, so that you can say, oh,

1 1 1j1 1 1 #!.99 (1 2 3 4 5)

and get

1 2 3 99 4 5

(The parens are needed to deal with the 99 hanging there.)

OK. on the one hand, if you read the description of # carefully enough, you will definitely find this. On the other hand, what part of using a complex number in this way is not an egregious albeit elegant hack?

Either way, it is a like a ninja lurking invisibly, ready to jump out and attack, until you become aware of this. I feel like Inspector Clouseau.

So I learn, at least, that all the operators, despite how obvious they seem to be when you do examples, may well have this kind of thing inside them … and it may well be something I need.

Where Does That Leave Us?

There’s a lot of meat in Tracy’s two notes to me, for which I’m grateful. And it becomes more and more clear that a good pair who knew J could be useful. I would probably have to rein him in all the time, to explain steps that are obvious to him and not to me, but it would probably save me a lot of time looking things up, experimenting, and not understanding.

And I’m sure it would help with syntax. Part of what you have to do here is get facile with the operators, doing them in the right order, avoiding parens, and so on.

I should mention, by the way, that I am trying to do this in the style of a “real” J programmer, namely fairly long cascaded expressions, and newly defined operators. A procedural-looking solution might be possible but it wouldn’t be close to the right style.

So I have learned to write this new verb:

tenner =: 1 j. 10&=

which applied thusly

(tenner rolls) # rolls

turns

4 5 4 5 10 4 5 4 5 4 5 10 4 5 4 5 4 5

into

4 5 4 5 10 0 4 5 4 5 4 5 10 0 4 5 4 5 4 5

with those nice shiny new zeros.

If I save that value into rollsx, I know that

10 2 $ rollsx

will give me

4 5
4 5
10 0
4 5
4 5
4 5
10 0
4 5
4 5
4 5

And I know I can transpose that, add a row of zeros, and transpose back like this:

: ( : 10 2 $ rollsx) , 0

resulting in this, which looks like something I think I want:

 4 5 0
 4 5 0
10 0 0
 4 5 0
 4 5 0
 4 5 0
10 0 0
 4 5 0
 4 5 0
 4 5 0

That looks a lot like the frame scores I want, without the bonuses plugged in. For now, that’s all I know. I’ve written this up this morning, and not learned any new stuff yet.

Bottom Line

I’m finding this difficult. There are all these operators. They all have rather complex behavior, and sometimes very surprising little twists like that trick with the complex numbers. None of them seems to apply very directly to what I want to do. I’m not sure whether this is because I picked a problem that doesn’t go into J easily, or whether I’m just very much a beginner so far. I’m supposing it is some of each.

I am frustrated, despite the willing help of the folks who hear me tweet. I’m rather glad I’ve put these posts out, as now if I quit, everyone will know it. Unless I delete the posts. Then only the four of you reading them will know.

Anyway, for now, I’m pushing forward. And this stuff is not fitting smoothly into what I know.

Thanks!