我正在尝试在基管周围构建一个包装器
|>
,对左侧进行一些修改,然后正常通过管道向前传输。在研究此问题时,我发现与其他操作员相比,基管具有以下特点:
按预期工作:
`+`(1,2)
#> [1] 3
`<-`("foo", 1)
foo
#> [1] 1
library(magrittr)
`%>%`(1, print)
#> [1] 1
未按预期工作:
`|>`(1, print)
#> Error in `|>`(1, print): could not find function "|>"
这意味着,例如,虽然以下内容适用于
magrittr
管道
as.call(c(as.name("%>%"), "foo", substitute(print)))
#> "foo" %>% print
并且可以传递给
eval()
:
eval(as.call(c(as.name("%>%"), "foo", substitute(print))))
#> [1] "foo"
它不适用于基管:
eval(as.call(c(as.name("|>"), "foo", substitute(print))))
#> Error in `|>`("foo", print): could not find function "|>"
我一直在努力寻找这方面的文档,因为我不太确定如何描述这个问题,而且谷歌通常不能很好地处理涉及特殊字符的查询,即使是在引号中。
编辑:有关上下文的更多详细信息
作为一个玩具示例,假设我们想要制作一个管道变体,通过管道传输对象的名称,而不是对象,并且不改变我们的用法:
library(magrittr)
`%>>%` <- function(lhs, rhs) {
# get lhs as a character
lhs.name <- deparse(substitute(lhs))
# the parent environment
parent <- parent.frame()
# the environment in which to evaluate pipeline
env <- new.env(parent = parent)
# magrittr version
eval(
as.call(c(as.name("%>%"), lhs.name, substitute(rhs))),
env, env
)
}
foo_func <- function(arg1, arg2, arg3) {
print(arg1)
print(arg2)
print(arg3)
arg2 + arg3
}
thing %>>% foo_func(2,4)
#> [1] "thing"
#> [1] 2
#> [1] 4
#> [1] 6
为了避免
magrittr
依赖性,我有兴趣使用 |>
而不是 %>%
来完成这项工作。看来我们可以替换为
eval(
str2lang(paste0("'", lhs.name, "'", " |> ", deparse(substitute(rhs)))),
env, env
)
虽然我还没有彻底测试过。
如果问题是如何在没有依赖关系的情况下实现“%>>%”,则从 poorman 源代码复制
insert_dot
源代码
https://github.com/nathaneastwood/poorman/blob/master/R/pipe.R
并将同一页面的%>%
源码修改为:
"%>>%" <- function(lhs, rhs) {
rhs_call <- insert_dot(substitute(rhs))
eval(rhs_call, envir = list(`.` = substitute(lhs)), enclos = parent.frame())
}
# tests
if (exists("xyz")) rm(xyz)
xyz %>>% paste0("*")
## [1] "xyz*"
xyz %>>% paste(., .)
## [1] "xyz xyz"