Setting the pipe so that it does not put . automatically as first argument

While using the pipe the lhs is automatically placed as the first argument of the rhs. This leads to the fact that both codes are equal:

library(dplyr)
1:10 %>% mean(na.rm = TRUE) # same as...
1:10 %>% mean(., na.rm = TRUE)

I just come into a situation where I needed the pipe to stop automatically using . as the first argument (as asked here). And in fact I never do 1:10 %>% mean(na.rm = TRUE), i.e. I always explicitly supply the first argument with . while using the pipe. Therefore I am wondering whether it is possible to prevent the pipe from always automatically put . as the first argument.

This means %>% should behave by default as if the rhs was in curly brackets:

1:10 %>% {mean(na.rm = TRUE)} 
# Returns an error since x is missing. This is expected! Again: I
# want %>% not to automatically provide the first argument with .

There is a similiar question. But in my case I want %>% by default prevent from this behavior.

>Solution :

A pipe that explicitly replaces a placeholder can be implemented (fairly) straightforwardly since the base R function substitute implements the bulk of this. The one caveat is that substitute expects an unquoted expression, so we need to work around that, and we obviously need to evaluate the resulting expression:

`%>%` = function (lhs, rhs) {
  subst = call('substitute', substitute(rhs), list(. = lhs))
  eval.parent(eval(subst))
}

Here I am reusing the %>% operator but if you are concerned about conflicts with ‘magrittr’ you may obviously use another operator, e.g. %|%.

$ 1:5 %>% sum(na.rm = TRUE, .) %>% identity()
# Error in identity() : argument "x" is missing, with no default
$ 1:5 %>% sum(na.rm = TRUE, .) %>% identity(.)
# [1] 15

Leave a Reply