lazy evaluation and scoping ?
I think actually it's both lazy evaluation and scoping. Here is how I understand it. Consider:
flist <- vector("list",2) ## creates the empty list
for(i in 1:2)slist[[i]] <- function()i
Now the RHS of the assignment is a function that returns the value of i. That is:
flist
function()i <environment: 0x04e3af4c> [[2]] function()i <environment: 0x04e3ae18> So the question is: what will be the value of i when the function is invoked? By R's lexical scoping rules it will be the value of i in the enclosing environment of the function, which is the value of i in the environment when the function is **defined** . This will be i = 2, the last value of the for loop on exit. This is due to lazy evaluation -- the value of i is not needed until the for() ends, as one can find by:
sapply(flist,function(z)as.list(environment(z)))
$i [1] 2 $i [1] 2 Hence one gets the results you originally saw. Adding the force(i) statement forces i to be evaluated separately at each iteration of the loop, thus placing the current values of i at each iteration into each function's enclosing environment. HTH. -- Bert Gunter -----Original Message----- From: r-help-bounces at r-project.org [mailto:r-help-bounces at r-project.org] On Behalf Of Antonio, Fabio Di Narzo Sent: Saturday, December 06, 2008 7:28 PM To: Gabor Grothendieck Cc: r-help at r-project.org Subject: Re: [R] unexpected scoping behavior with functions created in a loop 2008/12/6 Gabor Grothendieck <ggrothendieck at gmail.com>:
The missing item is lazy evaluation. Try forcing the evaluation of i
and then repeat:
makeF <- function(i) { force(i); function() i }
Tnx! That works! Sometimes lazy evaluation + side effects is just too much (complicated) for me:D bests, a.
On Sat, Dec 6, 2008 at 9:22 PM, Antonio, Fabio Di Narzo <antonio.fabio at gmail.com> wrote:
Hi guys. I recently stumbled on an unexpected behavior of R when using functions created in a loop. The problem is silly enough to me that I had hard time choosing a good mail subject, not talking about searching in the archives... After some experiments, I trimmed down the following minimal reproducible example: ####### makeF <- function(i) function() i fList <- list(makeF(1), makeF(2)) sapply(fList, do.call, list()) ##This works as expected (by me...): #[1] 1 2 ##Things go differently when creating functions in a for loop: for(i in 1:2) fList[[i]] <- makeF(i) sapply(fList, do.call, list()) #[1] 2 2 ##Same result with "lapply": fList <- lapply(as.list(1:2), makeF) sapply(fList, do.call, list()) #[1] 2 2 ####### I evidently overlook some important detail, but I still can't get it. Somebody can explain me what's happening there? Bests, antonio.
R.version
_ platform i686-pc-linux-gnu arch i686 os linux-gnu system i686, linux-gnu status Patched major 2 minor 8.0 year 2008 month 12 day 04 svn rev 47063 language R version.string R version 2.8.0 Patched (2008-12-04 r47063) -- Antonio, Fabio Di Narzo Ph.D. student at Department of Statistical Sciences University of Bologna, Italy
______________________________________________ R-help at r-project.org mailing list https://stat.ethz.ch/mailman/listinfo/r-help PLEASE do read the posting guide
http://www.R-project.org/posting-guide.html
and provide commented, minimal, self-contained, reproducible code.
Antonio, Fabio Di Narzo Ph.D. student at Department of Statistical Sciences University of Bologna, Italy ______________________________________________ R-help at r-project.org mailing list https://stat.ethz.ch/mailman/listinfo/r-help PLEASE do read the posting guide http://www.R-project.org/posting-guide.html and provide commented, minimal, self-contained, reproducible code.