Search code examples
tacit-programmingj

How can I define a verb in J that applies a different verb alternately to each atom in a list?


Imagine I've defined the following name in J:

m =: >: i. 2 4 5

This looks like the following:

 1  2  3  4  5
 6  7  8  9 10
11 12 13 14 15
16 17 18 19 20

21 22 23 24 25
26 27 28 29 30
31 32 33 34 35
36 37 38 39 40

I want to create a monadic verb of rank 1 that applies to each list in this list of lists. It will double (+:) or add 1 (>:) to each alternate item in the list. If we were to apply this verb to the first row, we'd get 2 3 6 5 10.

It's fairly easy to get a list of booleans which alternate with each item, e.g., 0 1 $~{:$ m gives us 0 1 0 1 0. I thought, aha! I'll use something like +:`>: @. followed by some expression, but I could never quite get it to work.

Any suggestions?

UPDATE

The following appears to work, but perhaps it can be refactored into something more elegant by a J pro.

poop =: monad define
    (($ y) $ 0 1 $~{:$ y) ((]+:)`(]>:) @. [)"0 y
)

Solution

  • I would use the oblique verb, with rank 1 (/."1)- so it applies to successive elements of each list in turn.

    You can pass a gerund into /. and it applies them in order, extending cyclically.

       +:`>: /."1 m 
     2
     3
     6
     5
    10
    
    12
     8
    16
    10
    20
    
    22
    13
    26
    15
    30
    
    32
    18
    36
    20
    40
    
    
    42
    23
    46
    25
    50
    
    52
    28
    56
    30
    60
    
    62
    33
    66
    35
    70
    
    72
    38
    76
    40
    80