【问题标题】:Function Factory in RR中的函数工厂
【发布时间】:2013-11-14 00:30:15
【问题描述】:

我尝试通过返回专门函数的字典来创建函数工厂,或多或少类似于函数式编程风格。我尝试在以下代码中执行此操作。

require(hash)

names = c("aa","bb","cc");
funs = hash()
for (i in seq(length(names))) {
  n = names[i]
  funs[[n]] = function(x) { 
    print(paste(n,":",x, sep="")) 
 }
}

显然,我在数组中有 3 个函数;但是,它们的行为都与迭代中的最后一个函数相同。

> funs[["aa"]](1)
[1] "cc:1"
> funs[["bb"]](2)
[1] "cc:2"
> funs[["cc"]](3)
[1] "cc:3"

我的猜测是 R 没有创建新的函数实例,而是在 for 循环中重用了相同的函数对象。

我尝试以下方法,希望 R 会创建不同的函数对象,

  funs[[n]] = eval(parse(text="function(x) { print(paste(n,':',x, sep='')) }"))

但它的工作原理与第一个相同。

你知道如何创建一个生成器来创建不同的函数对象吗?

【问题讨论】:

  • 我怀疑这是一个惰性评估问题。

标签: r functional-programming


【解决方案1】:

根据Hadley的Advanced R Programmin, Lexical scopingfuns[['aa']]funs[['bb']]funs[['cc']]函数体中的变量n<environment: R_GlobalEnv>中的变量n

例如:

> funs[["aa"]](1)
[1] "cc:1"
> n <- "1234"
> funs[["aa"]]("1")
[1] "1234:1"

为了做你想做的事,我会写一个返回函数的函数:

funs.gen <- function(n) {
  force(n)
  function(x) {
    print(paste(n, ":", x, sep=""))
  }  
}

names = c("aa","bb","cc");
funs = hash()
for (i in seq(length(names))) {
  n = names[i]
  funs[[n]] = funs.gen(n)
}

funs[["aa"]](1)
funs[["bb"]](2)
funs[["cc"]](3)

注意force 用于询问 R 不惰性求值表达式n。如果您删除它,那么 R 将在 for 循环之外评估 n,这将产生与您的问题相同的结果。

【讨论】:

  • 有效!感谢您的建议和参考。现在我了解到 for 循环中的 function(){} 确实创建了不同的函数实例。使用 force() 将不同的值与函数粘在一起,这样函数就可以独立使用了。
猜你喜欢
  • 2017-08-23
  • 1970-01-01
  • 1970-01-01
  • 2020-11-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-08-23
相关资源
最近更新 更多