# Order of `is assoc` and precedence traits matter, but should it?#6663

Open
opened this issue Jan 12, 2018 · 3 comments
Open

# Order of `is assoc` and precedence traits matter, but should it? #6663

opened this issue Jan 12, 2018 · 3 comments

### p6rt commented Jan 12, 2018

 Migrated from rt.perl.org#132713 (status was 'open') Searchable as RT132713\$ The text was updated successfully, but these errors were encountered:

### From @briandfoy

I originally asked this on StackOverflow​:

This fails to be right associative​:

sub infix​:<↑> ( Int​:D \n, Int​:D \m --> Int​:D )
is assoc<right>
is equiv(&infix​:<**>)
{ n ** m }

put "2**2**2**2 = ", 2**2**2**2;
put "2↑2↑2↑2 = ", 2↑2↑2↑2;
put "2↑ (2↑ (2↑2) ) = ", 2↑ (2↑ (2↑2) );

Reversing the traits fixes that​:

sub infix​:<↑> ( Int​:D \n, Int​:D \m --> Int​:D )
is equiv(&infix​:<**>)
is assoc<right>
{ n ** m }

I didn't see anything in the docs about the ordering of traits but
I wouldn't expect order to matter. Neither did I see anything saying I
couldn't combine traits.

As far as I can tell the precedence still works when it's specified first​:

sub infix​:<↑> ( Int​:D \n, Int​:D \m --> Int​:D )
is equiv(&infix​:<**>)
is assoc<right>
{ n ** m }

put "2↑3**4↑2 = ", 2↑2**2↑2;
put "2↑(3**(4↑2)) = ", 2↑2**2↑2;

put "2↑3*4↑2 = ", 2↑2*2↑2;
put "(2↑2)*(2↑2) = ", (2↑2)*(2↑2);

put "2↑3+4↑2 = ", 2↑2+2↑2;
put "(2↑2)+(2↑2) = ", (2↑2)+(2↑2);

How is this supposed to work? Should either way work? I can easily
imagine situations where I want to stack many traits​:

sub infix​:<↑> ( Int​:D \n, Int​:D \m --> Int​:D )
is equiv(&infix​:<**>)
is assoc<right>
is pure
is export
{ ... }

### From @zoffixznet

On Fri, 12 Jan 2018 00​:02​:34 -0800, comdog wrote​:

I originally asked this on StackOverflow​:

``````https://stackoverflow.com/q/48219788/2766176
``````

This fails to be right associative​:

``````sub infix&#8203;:\<↑> \( Int&#8203;:D \\n, Int&#8203;:D \\m  \-\-> Int&#8203;:D \)
is assoc\<right>
is equiv\(&infix&#8203;:\<\*\*>\)
\{ n \*\* m \}

put "2\*\*2\*\*2\*\*2 = ",      2\*\*2\*\*2\*\*2;
put "2↑2↑2↑2 = ",         2↑2↑2↑2;
put "2↑ \(2↑ \(2↑2\) \) = ",  2↑ \(2↑ \(2↑2\) \);
``````

Reversing the traits fixes that​:

``````sub infix&#8203;:\<↑> \( Int&#8203;:D \\n, Int&#8203;:D \\m  \-\-> Int&#8203;:D \)
is equiv\(&infix&#8203;:\<\*\*>\)
is assoc\<right>
\{ n \*\* m \}
``````

I didn't see anything in the docs about the ordering of traits but
I wouldn't expect order to matter. Neither did I see anything saying I
couldn't combine traits.

As far as I can tell the precedence still works when it's specified first​:

``````sub infix&#8203;:\<↑> \( Int&#8203;:D \\n, Int&#8203;:D \\m  \-\-> Int&#8203;:D \)
is equiv\(&infix&#8203;:\<\*\*>\)
is assoc\<right>
\{ n \*\* m \}

put "2↑3\*\*4↑2 = ",         2↑2\*\*2↑2;
put "2↑\(3\*\*\(4↑2\)\) = ",         2↑2\*\*2↑2;

put "2↑3\*4↑2 = ",         2↑2\*2↑2;
put "\(2↑2\)\*\(2↑2\) = ",        \(2↑2\)\*\(2↑2\);

put "2↑3\+4↑2 = ",         2↑2\+2↑2;
put "\(2↑2\)\+\(2↑2\) = ",         \(2↑2\)\+\(2↑2\);
``````

How is this supposed to work? Should either way work? I can easily
imagine situations where I want to stack many traits​:

``````sub infix&#8203;:\<↑>  \( Int&#8203;:D \\n, Int&#8203;:D \\m  \-\-> Int&#8203;:D \)
is equiv\(&infix&#8203;:\<\*\*>\)
is assoc\<right>
is pure
is export
\{ \.\.\. \}
``````

I pushed a fix to a branch[^1] as it appears to be blocked by RT#​132711.

More precisely, the fix fixes `is equiv` to *copy* associativity (per speculation[^2] and original[^3] behaviour). So in your code that would make it work right only on accident as `&infix​:<**>` is right-associative.

I also opened a doc issue to document that is equiv/tighter/looser set associativity as well as precedence.

### p6rt commented Jan 12, 2018

 The RT System itself - Status changed from 'new' to 'open'