如何定义管道操作员?

How to define the pipe operator?

提问人: 提问时间:3/29/2020 最后编辑:Ben 更新时间:5/29/2020 访问量:405

问:

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

我真的很好奇管道是如何定义的。到目前为止,我只是尝试将其分配给自己的操作员,但即使这样也不起作用。请看这里:

library(dplyr)

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

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

哪些神奇的成分使烟斗起作用?我们自己如何定义它?谢谢。

DPLYR Magrittr R 管道 分配操作员

评论

2赞 dvd280 3/29/2020
管道实际上不是 dplyr 函数,dplyr 从一个名为 magrittr 的包中导入它。您可以在文档中找到其定义:cran.r-project.org/web/packages/dplyr/index.html
0赞 3/29/2020
@dvd我做了一个编辑。根据定义,我指的是代码。在哪里可以找到它?
4赞 dvd280 3/29/2020
github.com/tidyverse/magrittr/tree/master/R
0赞 3/29/2020
@dvd 哇,这令人印象深刻,甚至里面还有很多功能也必须定义。谢谢。我复制并粘贴了所有的东西,它确实有效。但恐怕我不会得到所有这些:D至少暂时不会。.

答:

0赞 moodymudskipper 5/29/2020 #1

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 软件包 (v0.3.0) 于 2020-05-29 创建

评论

0赞 5/29/2020
谢谢! 显然是如何定义管道问题的答案。我不明白的是:我分配了显示的代码,在我的理解中,它应该制作管道,但它不起作用。我所做的是:magrittr:::pipemagrittr:::%>%`%>%` <- function () { function(lhs, rhs) { parent <- parent.frame() env <- new.env(parent = parent) chain_parts <- split_chain(match.call(), env = env)...
0赞 moodymudskipper 5/29/2020
由于split_chains等未导出,因此新管道无法再访问它,因为您在全局环境中定义了它。这并不是 magrittr 特有的