Understanding R function lazy evaluation

情到浓时终转凉″ 提交于 2019-12-11 06:12:28

问题


I'm having a little trouble understanding why, in R, the two functions below, functionGen1 and functionGen2 behave differently. Both functions attempt to return another function which simply prints the number passed as an argument to the function generator.

In the first instance the generated functions fail as a is no longer present in the global environment, but I don't understand why it needs to be. I would've thought it was passed as an argument, and is replaced with aNumber in the namespace of the generator function, and the printing function.

My question is: Why do the functions in the list list.of.functions1 no longer work when a is not defined in the global environment? (And why does this work for the case of list.of.functions2 and even list.of.functions1b)?

functionGen1 <- function(aNumber) {
  printNumber <- function() {
    print(aNumber)
  }
  return(printNumber)
}

functionGen2 <- function(aNumber) {
  thisNumber <- aNumber
  printNumber <- function() {
    print(thisNumber)
  }
  return(printNumber)
}

list.of.functions1 <- list.of.functions2 <- list()
for (a in 1:2) {
  list.of.functions1[[a]] <- functionGen1(a)
  list.of.functions2[[a]] <- functionGen2(a)
}

rm(a)

# Throws an error "Error in print(aNumber) : object 'a' not found"
list.of.functions1[[1]]()

# Prints 1
list.of.functions2[[1]]()
# Prints 2
list.of.functions2[[2]]()

# However this produces a list of functions which work
list.of.functions1b <- lapply(c(1:2), functionGen1)

回答1:


A more minimal example:

functionGen1 <- function(aNumber) {
  printNumber <- function() {
    print(aNumber)
  }
  return(printNumber)
}

a <- 1
myfun <- functionGen1(a)
rm(a)
myfun()
#Error in print(aNumber) : object 'a' not found

Your question is not about namespaces (that's a concept related to packages), but about variable scoping and lazy evaluation.

Lazy evaluation means that function arguments are only evaluated when they are needed. Until you call myfun it is not necessary to evaluate aNumber = a. But since a has been removed then, this evaluation fails.

The usual solution is to force evaluation explicitly as you do with your functionGen2 or, e.g.,

functionGen1 <- function(aNumber) {
  force(aNumber)
  printNumber <- function() {
    print(aNumber)
  }
  return(printNumber)
}

a <- 1
myfun <- functionGen1(a)
rm(a)
myfun()
#[1] 1


来源:https://stackoverflow.com/questions/41361844/understanding-r-function-lazy-evaluation

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!