Why is Insert (fold) right associative

108 views Asked by At

I expected

-/ 1 2 3 4
_8 NB. ((1-2)-3)-4

but I got

-/ 1 2 3 4
_2 NB. 1-(2-(3-4))

I there a reason for this? How do I get the associativity that I was expecting? If there are relevant sections in the book, could you link them please?

3

There are 3 answers

0
pmf On BEST ANSWER

It's the 'rightmost first' rule you can read about in Part 1: Getting Acquainted, 1: Basics.

From section 1.5 "Parentheses":

The rule, is that, in the absence of parentheses, the right argument of an arithmetic function is everything to the right.

So, -/ 1 2 3 4 resolves to 1 - 2 - 3 - 4 which by application of that rule is being interpreted as 1 - (2 - (3 - 4)).

As for your question, if there is a reason for it, the book argues in the same section that both, conventional associativity rules from "school mathematics" and this one, are "merely a convenience" to "reduce the number of parentheses we need to write". The advantage of resorting to this one in J should make computing a longer chain of functions explicitly intuitive by dropping the need to compare them according to an implicitly defined order that is visually unintuitive and needs to be remembered.

Later, in section 1.11 "Naming Scheme for Built-In Functions", you can find this very similar example, which uses >. instead of -. Note that 6 >. 5 is evaluated first "by rightmost-first rule":

   >. / 1 6 5
6
   1 >. 6 >. 5      NB. by the meaning of /
6
   1 >. (6 >. 5)    NB. by rightmost-first rule
6
   1 >. (6)         NB. by the meaning of >.
6
   1 >. 6           NB. by the meaning of ()
6
   6                NB. by the meaning of >.
6

To answer your question how to "get the associativity that I was expecting", think of what ((1 - 2) - 3) - 4 is actually doing without the help of parentheses: You want to sum all items with all but the first one negated, i.e. 1 + _2 + _3 + _4. So, use {. to get the head of the list (1), and }. to behead the list (2 3 4). Use - to negate the latter (producing _2 _3 _4), and @: to make it a fork, so we can use it with , to ravel both into a new list (1 _2 _3 _4), and compute its sum using +/:

   +/({.,-@:}.) 1 2 3 4
_8
0
bob On

It is also worthwhile to take a look at the Fold Conjunction group.

https://code.jsoftware.com/wiki/Vocabulary/fcap

It adds the sort of functionality that you are looking for, but with great power comes more complexity.

0
jthulhu On

The general solution is reverse the order of the arguments:

   -~/|. 1 2 3 4
_8

Step by step:

-~/|. 1 2 3 4
-~/ 4 3 2 1
4 -~ 3 -~ 2 -~ 1
4 -~ (3 -~ (2 -~ 1))   NB. right-associativity rule
(3 -~ (2 -~ 1)) - 4
((2 -~ 1) - 3) - 4
((1 - 2) - 3) - 4
_8

You could replace - with any dyadic verb.