I'm new to R, and I just discovered I suffer from Bracket Phobia (see comment in the link). I like the way magrittr
notation %>%
works, because it avoids nested parenthesis in some situations, and makes code more readable. I came from Mathematica
, where there is a very similar native //
notation to do what %>%
does. Here are some R and Mathematica comparisons:
#R Notation
c(1.5,-2.3,3.4) %>% round %>% abs %>% sum
#Mathematica Notation
{1.5,-2.3,3.4}//Round//Abs//Total
So far so good, but, my question is:
Is there some way to mimic Mathematica @ notation, with right-to-left associativity in R
?
Here is how it works in Mathematica, to solve the same code above:
Total@Abs@Round@{1.5,-2.3,3.4}
In Mathematica it can also be write as:
Total[Abs[Round[{1.5,-2.3,3.4}]]]
just like in R
it would be:
sum(abs(round(c(1.5,-2.3,3.4))))
But it would be much more clean (and cool) to have in R
something like this:
sum@abs@round@c(1.5,-2.3,3.4)
PS: I know @
is used in S4 classes, and is not a good idea. This is just an illustrative comparison.
The backpipe package was designed and created for this purpose. It provides a backpipe (right-to-left) operator for magrittr, pipeR and generally for any forward pipe operator. backpipe can be found on github and on CRAN.
library(magrittr) # or library(pipeR)
library(backpipe)
x <- c(1.5,-2.3,3.4)
sum %<% abs %<% round %<% x
all.equal( # TRUE
x %>% round %>% abs %>% sum,
sum %<% abs %<% round %<% x
)
backpipe also is not limited by additional parameters as is the case of the @BenBolker's solution. This, for example, works with backpipe :
mean(na.rm=TRUE) %<% c(1:3,NA)
See also the discussion on the magrittr github issue that discuss this.
I haven't tested/thought about this carefully at all, but defining function composition via an operator (as below) seems to work in a couple of test cases:
library(magrittr)
## operator defined as "left-pointing arrow" at the
## suggestion of @ClausWilke:
"%<%" <- function(x,y) { if (is(y,"function"))
function(z) x(y(z))
else x(y) }
x <- c(1.5,-2.3,3.4)
all.equal(x %>% round %>% abs %>% sum,
sum %<% abs %<% round %<% x)
x <- rnorm(1000)
all.equal(x %>% round %>% abs %>% sum,
sum %<% abs %<% round %<% x)
The syntax is not as nice as being able to use a single character (such as @
) for the composition operator, but even if you could find an unused one (all the obvious ones [!@#$%^&*~|]
are taken, and masking them would be a terrible idea) there's a parser limitation: user-defined binary operators in R must be of the form %?%
.
How about using compose
from hadley's purrr
package?
compose(sum,abs,round,c)(1.5,-2.3,3.4)
来源:https://stackoverflow.com/questions/31305342/is-right-to-left-operator-associativity-in-r-possible