了解 R 函数惰性求值
Understanding R function lazy evaluation
我有点难以理解为什么在 R 中,下面的两个函数 functionGen1
和 functionGen2
的行为不同。这两个函数都试图 return 另一个函数,它只打印作为参数传递给函数生成器的数字。
首先,生成的函数失败,因为 a
不再存在于全局环境中,但我不明白为什么需要这样。我原以为它是作为参数传递的,并在生成器函数和打印函数的命名空间中被 aNumber
替换。
我的问题是:当a
没有在全局环境中定义时,为什么列表list.of.functions1
中的函数不再起作用? (为什么这适用于 list.of.functions2
甚至 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)
一个更简单的例子:
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
你的问题不是关于命名空间(这是一个与包相关的概念),而是关于变量作用域和惰性求值。
惰性求值意味着函数参数只在需要时才求值。在您调用 myfun
之前,没有必要评估 aNumber = a
。但由于 a
已被删除,因此此评估失败。
通常的解决方案是像您对 functionGen2
或
所做的那样显式地强制求值
functionGen1 <- function(aNumber) {
force(aNumber)
printNumber <- function() {
print(aNumber)
}
return(printNumber)
}
a <- 1
myfun <- functionGen1(a)
rm(a)
myfun()
#[1] 1
我有点难以理解为什么在 R 中,下面的两个函数 functionGen1
和 functionGen2
的行为不同。这两个函数都试图 return 另一个函数,它只打印作为参数传递给函数生成器的数字。
首先,生成的函数失败,因为 a
不再存在于全局环境中,但我不明白为什么需要这样。我原以为它是作为参数传递的,并在生成器函数和打印函数的命名空间中被 aNumber
替换。
我的问题是:当a
没有在全局环境中定义时,为什么列表list.of.functions1
中的函数不再起作用? (为什么这适用于 list.of.functions2
甚至 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)
一个更简单的例子:
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
你的问题不是关于命名空间(这是一个与包相关的概念),而是关于变量作用域和惰性求值。
惰性求值意味着函数参数只在需要时才求值。在您调用 myfun
之前,没有必要评估 aNumber = a
。但由于 a
已被删除,因此此评估失败。
通常的解决方案是像您对 functionGen2
或
functionGen1 <- function(aNumber) {
force(aNumber)
printNumber <- function() {
print(aNumber)
}
return(printNumber)
}
a <- 1
myfun <- functionGen1(a)
rm(a)
myfun()
#[1] 1