我想创建一个R函数,它返回一个函数列表,每个函数都在列表的不同部分上运行。但是,由于R的范围规则,这似乎是不可能的。这是一个例子:
functiontest = function() {
foo = list()
for(i in 1:3) {
fixer = function(s) { return(
function() {
return(s)
}
)}
foo[[i]] = fixer(i)
}
return(foo)
}
functiontest()[[2]]() #returns 3
即使杀掉已命名的lambda“fixer”并使用立即函数也不能救我:
functiontest = function() {
foo = list()
for(i in 1:3) {
foo[[i]]=(function(s) { return(
function() {
return(s)
}
)})(i)
}
return(foo)
}
functiontest()[[2]]() #returns 3
我希望这返回2.我如何重构此代码以便实现这一点?
感谢。
答案 0 :(得分:3)
首先,您遇到的问题与范围无关。其次,我认为仅仅因为你不理解它而把一些愚蠢的东西称为是一个好主意。
在您的示例中,由于R中的延迟评估机制,列表中的所有函数都返回相同的值。请参阅help(force)
,它专门解决您的问题。简而言之,您需要在调用时强制评估函数,这可以通过添加force
来完成:
functiontest = function() {
foo = list()
for(i in 1:3) {
fixer = function(s) {
force(s) ### <<<---This is the only difference from your code ###
return(
function() {
return(s)
}
)}
foo[[i]] = fixer(i)
}
return(foo)
}
或者,使用更简洁的语法:
functiontest <- function() lapply(1:3, function(s) {s; function() s})
使用示例:
> L <- functiontest()
> L[[1]]()
[1] 1
> L[[2]]()
[1] 2
> L[[3]]()
[1] 3