How to define the pipe operator?

Viewed 348

I like the pipe (in or as mentioned in the comments) a lot but sometimes I run into errors which show me that I lack some understanding. In case of other functions or operators I mostly have at least some idea how they may be defined, but in case of the pipe I do not have even a clue where to start if I want to define it.

I am really curious how the pipe is defined. So far I simply tried to assign it to an own operator but even this does not work. See here:

library(dplyr)

`%pipe%` <- `%>%`

data.frame() %pipe% class(.)
# gives an error: subscript out of bounds

What magical ingredients make a pipe work? How could we define it ourselves? Thanks.

1 Answers

magrittr's code itself checks if the pipe you used is named as one of the few allowed names, as seen at the top here: https://github.com/tidyverse/magrittr/blob/master/R/is_something.R .

In fact all pipes have the same code, copied from magrittr:::pipe as seen as the bottom of this script :

https://github.com/tidyverse/magrittr/blob/master/R/pipe.R

The behavior depends on the name of the pipe, it's really odd and I've never seen this anywhere else.

I'll try to make it less confusing by inventing a fake function behaving likewise, forgive the silliness of the example.

concat <- function(x,y) {
  # extract quoted function name from call
  fun <- sys.call()[[1]]

  # check if it's one of our possible names, and act accordingly
  if(identical(fun, quote(`%upconcat>%`))) {
    return(toupper(paste0(x,y)))
  } 
  if(identical(fun, quote(`%lowconcat>%`))) {
    return(tolower(paste0(x,y)))
  } 
  stop("Unsupported operator!")
}
`%upconcat>%` <- `%lowconcat>%` <- concat

"XoX" %upconcat>% "oXo"
#> [1] "XOXOXO"
"XoX" %lowconcat>% "oXo"
#> [1] "xoxoxo"

`%foo>%` <- `%upconcat>%`
"XoX" %foo>% "oXo"
#> Error in "XoX" %foo>% "oXo": Unsupported operator!

You see there's no way to copy the pipe unless you modify the is_pipe function itself, which you can't do...

Just kidding, of course you can, but probably you shouldn't ?


library(magrittr)
is_pipe <- function(pipe) {
  identical(pipe, quote(`%>%`))   ||
    identical(pipe, quote(`%T>%`))  ||
    identical(pipe, quote(`%<>%`))  ||
    identical(pipe, quote(`%$%`)) ||
    identical(pipe, quote(`%pipe%`)) # <- added line
}

assignInNamespace("is_pipe", is_pipe, "magrittr")
`%pipe%` <- `%>%`

data.frame() %pipe% class(.)
#> [1] "data.frame"

Created on 2020-05-29 by the reprex package (v0.3.0)

Related