R:向功能工厂的管道输入

问题描述 投票:1回答:1

在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(),而第二种情况不需要?

r lazy-evaluation magrittr
1个回答
0
投票

由于此错误: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存储库中的问题)

© www.soinside.com 2019 - 2024. All rights reserved.