In R, how can I determine the operator precedence of user defined infix operators?

838 views Asked by At

Suppose I have two custom infix operators in R: %foo% and %bar%.

I have expressions that use both operators, such as:

x %foo% y %bar% z

How can I determine the operator precedence of %foo% and %bar%?

How can I change the precedence so that, for example, %bar% always executes before %foo%? In the example above this would be the same as:

x %foo% (y %bar% z)
2

There are 2 answers

0
Nick Kennedy On BEST ANSWER

I don't think this is explicitly documented, but implicit in the R language documentation is that infix operators are all of equal precedence and so are executed from left to right. This can be demonstrated as follows:

`%foo%` <- `+`
`%bar%` <- `*`
1 %bar% 2 %foo% 3
#5
1 %foo% 2 %bar% 3
#9

The only option I can think of would be to redefine one of the existing operators to do what you wanted. However, that itself would have repercussions so you might want to limit it to within a function.

It's also worth noting that using substitute does not change the operator precedence already set when the expression is first written:

eval(substitute(2 + 2 * 3, list(`+` = `*`, `*` = `+`)))
#10
2 * 2 + 3
#7
0
Tim Biegeleisen On

How can I determine the operator precedence of %foo% and %bar%?

You can't. R doesn't allow you to set the precedence of custom infix operators. User-defined infix operators have the default precedence rules which means they will be evaluated from left to right.

One reason for this limitation is that it would be extremely difficult and limiting to implement and maintain a set of precendence rules for infix operators. Imagine that you loaded an R package which comes with some custom infix operators. Then the relationship of the infix operators from the package to the %foo% and %bar% which you created would need to be defined. This will quickly become a serious burden.

As an example, imagine that package one contains infix operator %P1IF% and package two contains infix operator %P2IF%. Each package has defined that its infix operator should have the highest precedence. If you were to load both package one and two, then the following expression would be undefined:

v1 %P1IF% v2 %P2IF% v3
(v1 %P1IF% v2) %P2IF% v3     # package 2 doesn't expect this
v1 %P1IF% (v2 %P2IF% v3)     # package 1 doesn't expect this

Regardless of what the precedence might be the result for one of the two packages might be incorrect.