1

我看到 library(roxygen) 中的 Curry 函数出现了奇怪的行为。这是一个最小的例子:

library(roxygen)
library(foreach)

f <- function(x,y,z) { return(x+y+z) }

fns <- list()
foreach(i=c(1:10))  %do% {
  f[[i]] <- Curry(Curry(f,i),i)
}

在这种情况下,调用

f[[1]](0) 

返回 11。我期望 2。

有 2 个修复对我来说没有任何意义 - 一个是扁平化循环,如

fns <- list()
fns[[1]] <- Curry(Curry(f,1),1)
fns[[2]] <- Curry(Curry(f,2),2)
...

这样可行。此外,在原始循环中放置一个函数评估是可行的——如

fns <- list()
foreach(i=c(1:10)) %do% {
  f[[i]] <- Curry(Curry(f,i),i)
  f[[i]](27)
}

然后我们有

f[[1]](0) = 2.

这是怎么回事?

4

1 回答 1

3

在没有依赖关系的情况下重述问题

我假设Curry定义

Curry<-function(FUN,...) {
  dots<-list(...);
  function(...) do.call(FUN,c(dots,list(...)))}

然后

f <- function(x,y,z) list(x,y,z)
fns<-vector("list",10)
for(i in 1:10) {fns[[i]]<-Curry(Curry(c,i),i)}
fns[[1]](0)

产量

[1] 10  1  0

表明f直到循环完成后才评估 to 的第一个参数。

分析

这是由于惰性评估。

这里的罪魁祸首比解释一个懒惰的评估怪癖要微妙一些,这就是为什么我在标记为重复时犹豫不决。

这里延迟的是评估FUN

CurryF<-function(FUN,...) {
  force(FUN); #needed for nesting Curry
  dots<-list(...);
  function(...) do.call(FUN,c(dots,list(...)))}

现在再试一次

for(i in 1:10) {fns[[i]]<-CurryF(CurryF(c,i),i)}
fns[[1]](0)

对于预期的结果

[1] 1 1 0
于 2015-08-09T01:37:13.357 回答