R的功能工厂

use*_*165 6 functional-programming r

我尝试通过返回一个专门的函数字典来提出一个函数工厂,或多或少像函数式编程风格.我尝试在以下代码中执行此操作.

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="")) 
 }
}
Run Code Online (Sandbox Code Playgroud)

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

> funs[["aa"]](1)
[1] "cc:1"
> funs[["bb"]](2)
[1] "cc:2"
> funs[["cc"]](3)
[1] "cc:3"
Run Code Online (Sandbox Code Playgroud)

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

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

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

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

您是否知道如何创建一个创建不同功能对象的生成器?

wus*_*978 10

据哈德利的预研编程与规范,词法作用域,变量n中的函数体funs[['aa']],funs[['bb']]funs[['cc']]是可变n<environment: R_GlobalEnv>.

例如:

> funs[["aa"]](1)
[1] "cc:1"
> n <- "1234"
> funs[["aa"]]("1")
[1] "1234:1"
Run Code Online (Sandbox Code Playgroud)

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

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)
Run Code Online (Sandbox Code Playgroud)

注意,force用于询问R不是惰性求值表达式n.如果你删除它,那么R将评估n出的for,这将产生相同的结果,你的问题循环.