Search code examples
j

Amend with bond to new data shows unexpected behaviour


I have been using J for a couple of weeks now and recently started using it for simple problems rather than just toying with concepts.

This problem needs to replace all x characters in a string into y, which works but using a dyad form of the final verb gives me unexpected output.

Let's use the following example input:

input =. 'abcxdefxghi'

First, I need to find the indexes of x characters in the right argument for amend.

findx =. I.@:([:'x'&= ])
findx input   NB. 3 7
0 findx input NB. 3 7
1 findx input NB. 3 7

Then, I amend the results of findx with a bonded y on the left.

trxy =. 'y'&(findx })
trxy input     NB. abcydefyghi
_1 trxy input  NB. domain error
0 trxy input   NB. abcxdefxghi <= this is the really unexpected result
1 trxy input   NB. abcydefyghi <= somewhat unexpected, works with strictly positive ints
'a' trxy input NB. domain error

There is two things I don't understand:

  • why trxy sometimes works as a dyad when I thought I bonded the left side of my amend ?
  • why a 0 left argument stops trxy from working ?

Solution

  • With 1 trxy input you are executing 1 'y'&(findx }) input – and x u&n y is maybe not what you expect. It is documented (somewhat hidden) on the bottom of this page: https://code.jsoftware.com/wiki/Vocabulary/ampm

    It is equivalent to x (m&n @ ] ^: [) y, thus applies n on y (with m on the left side) for x times. That's why with 0 trxy y you aren't executing anything, thus y stays the same. With 1 trxy y you are applying trxy once to y. As trxy has no trivial inverse, _1 trxy y results in an error. And because 'a' isn't a number, the last one is just a plain error.

    If you – for whatever reason – just want to be able to write trxy as a monad and a dyad that ignores the left-hand side, you could use trxy =. 'y' findx} ]. (As you could also use findx =. I.@:('x' = ]) or just findx =. [:I. 'x'=].)