考虑
proper_filter <- function(.data, ...) {
code = substitute(filter(.data, ...))
print(names(parent.frame()))
}
fn_wo_magrittr <- function(dfr, val) {
proper_filter(dfr, speed < val)
}
fn_w_magrittr <- function(dfr, val) {
dfr %>%
proper_filter(speed < val)
}
val2 = 10
fn_wo_magrittr(cars, val2)
fn_w_magrittr(cars, val2)
当调用proper_filter
时,函数只打印在parent.frame()
中定义的名称。
fn_wo_magrittr
不使用{magrittr},因此它标识了定义了dfr
和val
的右侧parent.frame()
。
但是函数fn_wo_magrittr
使用{magrittr},因此parent.frame()
不是直接的调用环境,而是可能被%>%
更改。
如何找到合适的通话环境?调用%>%
的那个。我似乎想不通。
您试图做的事情可能不安全。据我所知,magrittr
并没有记录它运行时堆栈帧的样子,所以虽然你可能会让它工作,但它不一定会在下一个magrittr
版本中继续工作。
相反,您应该使用R管道|>
。它被记录为进行非常简单的语法操作,因此
dfr |>
proper_filter(speed < val)
被记录为与相同
proper_filter(dfr, speed < val)
R管道有几个缺点:它只在R 4.1.0或更新版本中可用,而且它更受限制,例如.
不支持作为占位符,所以也许你最好的方法是根本不使用管道。
1(显式传递环境通常,将环境传递给使用环境的函数更安全、更灵活。仍然可以使用parent.frame()
作为默认值,但使用显式参数可以处理一般情况。
library(magrittr)
val2 <- 10
proper_filter2 <- function(.data, ..., envir = parent.frame()) {
code <- substitute(filter(.data, ...))
print(ls(envir))
}
fn_w_magrittr2 <- function(dfr, val, .envir = environment()) {
dfr %>%
proper_filter2(speed < val, envir = .envir)
}
fn_w_magrittr2(cars, val2)
## [1] "dfr" "val"
2(公式另一种处理方法是使用公式,因为它们有环境。proper_filter3的公式参数应该是单侧公式。
library(magrittr)
val2 <- 10
proper_filter3 <- function(.data, formula) {
code <- substitute(filter(.data, rhs), list(rhs = formula[[2]]))
print(ls(environment(formula)))
}
fn_w_magrittr3 <- function(dfr, val) {
.formula <- ~ speed < val
dfr %>%
proper_filter3(.formula)
}
fn_w_magrittr3(cars, val2)
## [1] "dfr" "val"
3(pipe_ager_lexicalmagrittr包包含一个pipe_ageer_lexical,它当前未分配给中缀管道符号。它将在magrittr的下一个版本中定义,如本次提交所示,但与此同时,我们可以自己将其分配给中缀符号。
# as in question
proper_filter <- function(.data, ...) {
code = substitute(filter(.data, ...))
print(names(parent.frame()))
}
`%!>%` <- magrittr::pipe_eager_lexical # <------- note this definition
fn_w_magrittr4 <- function(dfr, val) {
dfr %!>%
proper_filter(speed < val)
}
val2 <- 10
fn_w_magrittr4(cars, val2)
## [1] "." "dfr" "val"
中的magrittr问题中对此进行了一些讨论https://github.com/tidyverse/magrittr/issues/171,https://github.com/tidyverse/magrittr/issues/38和https://github.com/tidyverse/magrittr/issues/70他们似乎得出结论,如果不牺牲magrittr的重要特征,就无法在magrittr内部以一般的方式解决这一问题,尽管magrittr热切的词汇管道就足够了。
上面展示了如何在仍然使用magrittr的情况下处理此问题,但替换magrittr也有可能。另一个答案提到|>
,Bizarro管道可以用于另一种解决方案,当然,不使用管道总是有可能的。