Why are the two functions fn and gn below different? I don't think they should be, but I must be missing something.
vars <- letters[1:10]
a <- b <- 1
fn <- function (d) {
sapply( vars, exists )
}
gn <- function (d) {
sapply( vars, function (x) { exists(x) } )
}
fn(d=2)
# a b c d e f g h i j
# TRUE TRUE TRUE FALSE FALSE FALSE FALSE FALSE TRUE FALSE
gn(d=2)
# a b c d e f g h i j
# TRUE TRUE TRUE TRUE FALSE FALSE FALSE FALSE FALSE FALSE
exists("i")
# [1] FALSE
There are two differences:
gn(d=2)says thatdexists, but why doesn'tfn(d=2)?fn(d=2)says thatiexists, whengn(d=2)does not. This is puzzling, because I haven't definedianywhere.
Note: This is on R version 3.2.0, it seems the second behavior is new to that version (see below).
Why
iis different...It looks like there were changes in R 3.2. An index variable
ihas been added to the current environment oflapply(which is whatsapplyactually calls). This goes along with the new behavior to force evaluation of the parameters passed along to the function you are applying over. This means that you now have access to the index of the current iteration you are on in the loop.The reason
fnandgnbehave differently is thatexists()looks in the environment where it is called. In the case offn, that is the environment where thisivariable has been created. In the case ofgn, it's looking in the environment of your anonymous function. When R cannot find a symbol in the local environment, it searches environments based on where functions where defined, not where they are called. This means R will not find theivariable since your anonymous function is defined in a place where theivariables does not exist.We can write a little helper function to make it easier to grab the current index.
As far as I can tell this is currently undocumented behavior. It may change in future versions of R.
Why
dis different...The discrepancy with the
dvariable is a more direct scoping issue. Again R is creating a new environment which it is using to call the functionexists. The parent of this environment is the base environment. So when you callexistsit looks where it was called from (which is this environment whereiexists) and since it doesn't finddthere, it searches the next parent which is the base environment. The current function environment is never searched. You could explicitly search the current environment withFor more information on environments in R I suggest you read the Environments section of Advanced R