j

Why is Insert (fold) right associative


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?


Solution

  • 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