【问题标题】:Understanding R function lazy evaluation理解 R 函数惰性求值
【发布时间】:2017-05-12 17:23:32
【问题描述】:

我很难理解为什么在 R 中,以下两个函数 functionGen1functionGen2 的行为不同。两个函数都试图返回另一个函数,该函数只是打印作为参数传递给函数生成器的数字。

在第一种情况下,生成的函数会失败,因为a 不再存在于全局环境中,但我不明白为什么需要它。我原以为它是作为参数传递的,并在生成器函数和打印函数的命名空间中被 aNumber 替换。

我的问题是:为什么list.of.functions1 列表中的函数在全局环境中没有定义a 时不再起作用? (为什么这适用于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)

【问题讨论】:

    标签: r function namespaces lazy-evaluation


    【解决方案1】:

    一个更简单的例子:

    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
    

    【讨论】:

    • 谢谢!将接受答案并更改问题标题以提及惰性评估。这让我很困惑,现在知道要搜索什么了。
    • 如果您不知道这个术语,您还应该查找“闭包”,因为那是您在那里创建的。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-01-13
    相关资源
    最近更新 更多