I'm seeing strange behavior with the Curry function from library(roxygen). Here's a minimal example:
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)
}
In this case the call
f[[1]](0)
returns 11. I expect 2.
There are 2 fixes that don't make any sense to me - one is to flatten the loop, as in
fns <- list()
fns[[1]] <- Curry(Curry(f,1),1)
fns[[2]] <- Curry(Curry(f,2),2)
...
That works. In addition, putting a single function evaluation in the original loops works - as in
fns <- list()
foreach(i=c(1:10)) %do% {
f[[i]] <- Curry(Curry(f,i),i)
f[[i]](27)
}
We then have
f[[1]](0) = 2.
What's going on?
I assume Curry
is defined as
Curry<-function(FUN,...) {
dots<-list(...);
function(...) do.call(FUN,c(dots,list(...)))}
Then
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)
Yields
[1] 10 1 0
showing that the first argument to f
was not evaluated until after the completion of the loop.
This is due to lazy evaluation.
The culprit here is a bit more subtle than Explain a lazy evaluation quirk, which is why I waffled on marking as a duplicate.
What's being delayed here is the evaluation of FUN
CurryF<-function(FUN,...) {
force(FUN); #needed for nesting Curry
dots<-list(...);
function(...) do.call(FUN,c(dots,list(...)))}
Now try again
for(i in 1:10) {fns[[i]]<-CurryF(CurryF(c,i),i)}
fns[[1]](0)
for the expected result
[1] 1 1 0