【问题标题】:How to define the pipe operator?如何定义管道运算符?
【发布时间】:2020-07-09 10:18:54
【问题描述】:

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

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

library(dplyr)

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

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

什么神奇的成分使管道起作用?我们怎么能自己定义呢?谢谢。

【问题讨论】:

  • 管道实际上不是 dplyr 函数,dplyr 从一个名为 magrittr 的包中导入它。你可以在文档中找到它的定义:cran.r-project.org/web/packages/dplyr/index.html
  • @dvd 我进行了编辑。根据定义,我的意思是代码。我在哪里可以找到它?
  • @dvd 哇,这令人印象深刻,其中甚至还有许多必须定义的函数。谢谢。我复制并粘贴了所有的东西,它确实有效。但恐怕我不会得到所有这些:D 至少暂时不会......

标签: dplyr magrittr r dplyr pipe assignment-operator magrittr


【解决方案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 package (v0.3.0) 于 2020 年 5 月 29 日创建

【讨论】:

  • 谢谢! magrittr:::pipe 显然是对如何定义管道的问题的答案。我不明白的是:我将magrittr::: 中显示的代码分配给%&gt;%,据我所知,这应该是管道,但它不起作用。我所做的是:`%&gt;%` &lt;- function () { function(lhs, rhs) { parent &lt;- parent.frame() env &lt;- new.env(parent = parent) chain_parts &lt;- split_chain(match.call(), env = env)...
  • 因为 split_chains 等未导出,所以您的新管道无法再访问它,因为您在全局环境中定义了它。这不是特定于 magrittr
猜你喜欢
  • 2019-07-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-06-29
  • 1970-01-01
  • 2015-10-08
  • 2017-05-25
  • 2017-10-18
相关资源
最近更新 更多