如何覆盖 magrittr 管道运算符?
How to override magrittr pipe operator?
假设我有一个数据集,我想使用管道语法对其应用多个过滤器,如下所示:
library(magrittr)
library(dplyr)
mtcars %<>%
filter(cyl == 4) %>%
select(cyl, mpg)
nrow(mtcars)
#[1] 11
我在每个这样的步骤之后用 nrow
检查数据集的当前状态,所以我想我可以沿着
的线路覆盖管道 %<>%
运算符
`%<?>%` <- function(lhs, rhs) {
x <- magrittr::`%<>%`(lhs, rhs)
if (is.data.frame(x) & pipeVerbose) print(nrow(x))
}
#Using this will generate errors like
#Error in pipes[[i]] : subscript out of bounds
现在通过打开或关闭 pipeVerbose
标志,我可以控制整个流程的跟踪过程。显然不是那么简单,因为内部评估机制,如提示。问题是,是否有可能以最小的努力实现所需的行为,即不修补 magittr
内部结构?
我不得不承认整个想法有点令人不安,但我的实际情况有点复杂,我想通过一个简单的 on/off 隐藏一些 debug/development 演示目的的详细信息切换。
您可以使用一个 TaskCallback
,它会在顶层任务完成时执行。在回调中检查表达式是否包含 %<>%
运算符,如果是则打印结果:
printAssignmentPipe <- function(exp, res, success, printed){
if (any(grepl("%<>%", exp, fixed = T))) {
print(res)
}
TRUE
}
addTaskCallback(printAssignmentPipe)
您可以轻松地扩展回调以检查 pipeVerbose
的值,或者您只需将 addTaskCallback
和 removeTaskCallback
调用到 activate/deactivate。
由于链利用惰性评估,更好的翻译应该是这样的:
`%<?>%` <- function(lhs, rhs) {
call <- match.call()
call[[1]] <- quote(`%<>%`)
x <- eval.parent(call)
if (is.data.frame(x) & pipeVerbose) print(nrow(x))
}
我们基本上重写了函数调用并对其进行评估。
请注意,您可以 on/off 以这种方式切换,并不比使用 %<?>%
而不是 %<>%
更明显:
p <- function(x){if(pipeVerbose) print(nrow(x))}
pipeVerbose <- FALSE
mtcars %<>%
filter(cyl == 4) %>%
select(cyl, mpg) %T>% p
rm(mtcars)
pipeVerbose <- TRUE
mtcars %<>%
filter(cyl == 4) %>%
select(cyl, mpg) %T>% p
假设我有一个数据集,我想使用管道语法对其应用多个过滤器,如下所示:
library(magrittr)
library(dplyr)
mtcars %<>%
filter(cyl == 4) %>%
select(cyl, mpg)
nrow(mtcars)
#[1] 11
我在每个这样的步骤之后用 nrow
检查数据集的当前状态,所以我想我可以沿着
%<>%
运算符
`%<?>%` <- function(lhs, rhs) {
x <- magrittr::`%<>%`(lhs, rhs)
if (is.data.frame(x) & pipeVerbose) print(nrow(x))
}
#Using this will generate errors like
#Error in pipes[[i]] : subscript out of bounds
现在通过打开或关闭 pipeVerbose
标志,我可以控制整个流程的跟踪过程。显然不是那么简单,因为内部评估机制,如提示magittr
内部结构?
我不得不承认整个想法有点令人不安,但我的实际情况有点复杂,我想通过一个简单的 on/off 隐藏一些 debug/development 演示目的的详细信息切换。
您可以使用一个 TaskCallback
,它会在顶层任务完成时执行。在回调中检查表达式是否包含 %<>%
运算符,如果是则打印结果:
printAssignmentPipe <- function(exp, res, success, printed){
if (any(grepl("%<>%", exp, fixed = T))) {
print(res)
}
TRUE
}
addTaskCallback(printAssignmentPipe)
您可以轻松地扩展回调以检查 pipeVerbose
的值,或者您只需将 addTaskCallback
和 removeTaskCallback
调用到 activate/deactivate。
由于链利用惰性评估,更好的翻译应该是这样的:
`%<?>%` <- function(lhs, rhs) {
call <- match.call()
call[[1]] <- quote(`%<>%`)
x <- eval.parent(call)
if (is.data.frame(x) & pipeVerbose) print(nrow(x))
}
我们基本上重写了函数调用并对其进行评估。
请注意,您可以 on/off 以这种方式切换,并不比使用 %<?>%
而不是 %<>%
更明显:
p <- function(x){if(pipeVerbose) print(nrow(x))}
pipeVerbose <- FALSE
mtcars %<>%
filter(cyl == 4) %>%
select(cyl, mpg) %T>% p
rm(mtcars)
pipeVerbose <- TRUE
mtcars %<>%
filter(cyl == 4) %>%
select(cyl, mpg) %T>% p