views:

162

answers:

2

I've been using J for a few months now, and I find that reading unfamiliar code (e.g. that I didn't write myself) is one of the most challenging aspects of the language, particularly when it's in tacit. After a while, I came up with this strategy:

1) Copy the code segment into a word document

2) Take each operator from (1) and place it on a separate line, so that it reads vertically

3) Replace each operator with its verbal description in the Vocabulary page

4) Do a rough translation from J syntax into English grammar

5) Use the translation to identify conceptually related components and separate them with line breaks

6) Write a description of what each component from (5) is supposed to do, in plain English prose

7) Write a description of what the whole program is supposed to do, based on (6)

8) Write an explanation of why the code from (1) can be said to represent the design concept from (7).

Although I learn a lot from this process, I find it to be rather arduous and time-consuming -- especially if someone designed their program using a concept I never encountered before. So I wonder: do other people in the J community have favorite ways to figure out obscure code? If so, what are the advantages and disadvantages of these methods?

EDIT:

An example of the sort of code I would need to break down is the following:

binconv =: +/@ ((|.@(2^i.@#@])) * ]) @ ((3&#.)^:_1)

I wrote this one myself, so I happen to know that it takes a numerical input, reinterprets it as a ternary array and interprets the result as the representation of a number in base-2 with at most one duplication. (e.g., binconv 5 = (3^1)+2*(3^0) -> 1 2 -> (2^1)+2*(2^0) = 4.) But if I had stumbled upon it without any prior history or documentation, figuring out that this is what it does would be a nontrivial exercise.

+4  A: 

Try breaking the verb up into its components first, and then see what they do. And rather than always referring to the vocab, you could simply try out a component on data to see what it does, and see if you can figure it out. To see the structure of the verb, it helps to know what parts of speech you're looking at, and how to identify basic constructions like forks (and of course, in larger tacit constructions, separate by parentheses). Simply typing the verb into the ijx window and pressing enter will break down the structure too, and probably help.

Consider the following simple example: <.@-:@#{/:~

I know that <. -: # { and /: are all verbs, ~ is an adverb, and @ is a conjunction (see the parts of speech link in the vocab). Therefore I can see that this is a fork structure with left verb <.@-:@# , right verb /:~ , and dyad { . This takes some practice to see, but there is an easier way, let J show you the structure by typing it into the ijx window and pressing enter:

   <.@-:@#{/:~
+---------------+-+------+
|+---------+-+-+|{|+--+-+|
||+--+-+--+|@|#|| ||/:|~||
|||<.|@|-:|| | || |+--+-+|
||+--+-+--+| | || |      |
|+---------+-+-+| |      |
+---------------+-+------+

Here you can see the structure of the verb (or, you will be able to after you get used to looking at these). Then, if you can't identify the pieces, play with them to see what they do.

   10?20
15 10 18 7 17 12 19 16 4 2
   /:~ 10?20
1 4 6 7 8 10 11 15 17 19
   <.@-:@# 10?20
5

You can break them down further and experiment as needed to figure them out (this little example is a median verb).

J packs a lot of code into a few characters and big tacit verbs can look very intimidating, even to experienced users. Experimenting will be quicker than your documenting method, and you can really learn a lot about J by trying to break down large complex verbs. I think I'd recommend focusing on trying to see the grammatical structure and then figure out the pieces, building it up step by step (since that's how you'll eventually be writing tacit verbs).

Jordan
Interesting. I never broke things down explicitly in terms of parts of speech before -- typically my thinking stays at the level of structure vs. substance operators, at least when I'm decoding the tacit verbs in the J phrasebook for practice, or trying to figure out what the heck Roger Hui was thinking when he wrote his Project Euler solutions.
estanford
+1  A: 

(I'm putting this in the answer section instead of editing the question because the question looks long enough as it is.)

I just found an excellent paper on the jsoftware website that works well in combination with Jordan's answer and the method I described in the question. The author makes some pertinent observations:

1) A verb modified by an adverb is a verb.

2) A train of more than three consecutive verbs is a series of forks, which may have a single verb or a hook at the far left-hand side depending on how many verbs there are.

This speeds up the process of translating a tacit expression into English, since it lets you group verbs and adverbs into conceptual units and then use the nested fork structure to quickly determine whether an instance of an operator is monadic or dyadic. Here's an example of a translation I did using the refined method:

d28=: [:+/\{.@],>:@[#(}.-}:)@]%>:@[

[: +/\

{.@] ,

>:@[ #

(}.-}:)@] %

>:@[
  • cap (plus infix prefix)

    (head atop right argument) ravel

    (increment atop left argument) tally

    (behead minus curtail) atop right argument

    divided by

    increment atop left argument

  • the partial sums of the sequence defined by

    the first item of the right argument, raveled together with

    (one plus the left argument) copies of

    (all but the first element) minus (all but the last element)

    of the right argument, divided by

    (one plus the left argument).

  • the partial sums of the sequence defined by

    starting with the same initial point,

    and appending consecutive copies of points derived from the right argument by

    subtracting each predecessor from its successor

    and dividing the result by the number of copies to be made

  • Interpolating x-many values between the items of y
estanford