在R中,我有一个输出函数的函数(称为函数工厂)。但是,用%>%
用管道传递输入时,会产生奇怪的错误。
这是一个简化的示例:
ax <- function(a) {
function(x) a*x
}
library(magrittr)
3 %>% ax() %>% plot # Error in a * x : non-numeric argument to binary operator
ax(3) %>% plot # works, a plot of y=3x is produced
Hadley's book使我尝试将force(a)
插入ax
的功能主体中。现在,在两种情况下都将生成一个图。
但是我对为什么这样做感到困惑。对我而言,这两种情况实质上是相同的。为什么第一种情况需要force()
,而第二种情况不需要?
由于此错误:https://github.com/tidyverse/magrittr/issues/195
两年没有人碰过管道代码。
它们的根本问题是R Lazy评估。当您将参数传递给函数时,直到需要它时才对其求值。
例如,请尝试以下代码:
funs <- list()
for (i in 1:3) {
funs[[i]] <- ax(i)
}
# i is not evaluated until now. it has been modified before it is evaluated so all the calls evaluate a to the current value of i (i=3)
print(funs[[3]](1))
print(funs[[2]](1))
print(funs[[1]](1))
# lapply creates an environment for each iteration. Even though the evaluation is delayed, it maps to the expected value of a
funs2 <- lapply(1:3, ax)
print(funs2[[3]](1))
print(funs2[[2]](1))
print(funs2[[1]](1))
如果添加force(a)
,则在调用a
时强制执行ax
的求值,而不是在调用funs [[i]]时强制求值,得到预期的行为。
如果我确切地找到了导致错误发生的原因,我可能已经向magrittr提交了拉取请求。也许值得花一些时间进行调试……或者也许有人会很快实现一个基于Rlang的管道,这种管道较小且易于遵循,可以解决大多数magrittr缺点。 (有关更多详细信息,请参阅magrittr存储库中的问题)