Dplyr 的mutate
函数可以评估“链式”表达式,例如
library(dplyr)
data.frame(a = 1) %>%
mutate(b = a + 1, c = b * 2)
## a b c
## 1 1 2 4
如何实施?快速浏览 dplyr 的源代码会发现候选代码的基本结构:
library(lazyeval)
library(rlang)
compat_as_lazy <- function(quo) {
structure(class = "lazy", list(
expr = f_rhs(quo),
env = f_env(quo)
))
}
compat_as_lazy_dots <- function(...) {
structure(class = "lazy_dots", lapply(quos(...), compat_as_lazy))
}
my_mutate <- function(.data, ...) {
lazy_eval(compat_as_lazy_dots(...), data = .data)
}
data.frame(a = 1) %>%
my_mutate(b = a + 1, c = b * 2)
## Error in eval(x$expr, data, x$env) : object 'b' not found
...但是这种“幼稚”的实现不起作用,并且背后的 C++ 代码mutate_impl
非常复杂。我知道它不起作用,因为lazy_eval
on "lazy_dots"
uses lapply
,即每个表达式都是相互独立地评估的,而我宁愿需要链式评估并将结果返回到共享环境。如何让它发挥作用?