如何定义管道操作符?

How to define the pipe operator?

我非常喜欢管道(如评论中所述,在 or 中)但有时我 运行 会出错,这表明我缺乏一些理解。对于其他函数或运算符,我大多至少知道如何定义它们,但对于管道,如果我想定义它,我什至不知道从哪里开始。

我很好奇管道是怎么定义的。到目前为止,我只是试图将它分配给自己的操作员,但即使这样也行不通。看这里:

library(dplyr)

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

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

是什么神奇的成分让管道发挥作用?我们如何自己定义它?谢谢

magrittr 的代码本身会检查您使用的管道是否被命名为少数允许的名称之一,如顶部所示:https://github.com/tidyverse/magrittr/blob/master/R/is_something.R .

事实上,所有管道都有相同的代码,从 magrittr:::pipe 复制而来,如脚本底部所示:

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

行为取决于管道的名称,这真的很奇怪,我从未在其他任何地方见过这种情况。

我会尝试通过发明一个行为类似的假函数来减少混淆,请原谅这个例子的愚蠢。

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!

你看没有办法复制管道,除非你修改 is_pipe 函数本身,你不能这样做...

开个玩笑,当然可以,但可能不应该?


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"

reprex package (v0.3.0)

于 2020-05-29 创建