2012-04-04 45 views
5

我试图使用一系列lapply调用来构建一个curried函数列表,理想情况下在最后lapply调用返回最终的期望值。咖啡的工作,但lapply似乎始终应用第二个应用程序后列表中的最后一个元素。为什么重复调用lapply后闭包中的变量值会丢失?

例子:

curry <- function(fn, ...) { 
    arglist <- list(...) 
    function(...) { 
    do.call(fn, append(arglist, list(...))) 
    } 
} 
# rcurry is used only to init the first lapply. 
rcurry <- function(v1, fn, ...) { 
    arglist <- append(list(v1), list(...)) 
    function(...) { 
    do.call(fn, append(arglist, list(...))) 
    } 
} 

myadd <- function(a,b,c) { 
    a+b+c 
} 

这按预期工作:

# you can achieve the same by closure: 
# curry.a <- lapply(c(10, 1000), FUN = function(a) { curry(myadd, a) }) 
curry.a <- lapply(list(10, 1000), rcurry, myadd) 
curry.a[[1]](1,2) 
curry.a[[2]](1,2) 

# > [1] 13 
# > [1] 1003 

curry下一个lapply “轧液范围”:

# this does give the desired output: 
# curry.a.b <- list(curry(curry.a[[1]], 1), curry(curry.a[[2]], 1)) 
curry.a.b <- lapply(curry.a, curry, 1) 
curry.a.b[[1]](2) 
curry.a.b[[2]](2) 

# > [1] 1003 
# > [1] 1003 

它似乎并不像一个curryrcurry函数的结果。使用roxygenCurry函数可以做同样的事情。通过关闭创建curry.a或使用curry.a <- list(curry(myadd, 10), curry(myadd, 1000))也会得到相同的结果。

当然,最终咖喱:

# it doesn't work if you re-define this: 
# curry.a.b <- list(curry(curry.a[[1]], 1), curry(curry.a[[2]], 2)) 
curry.a.b.c <- lapply(curry.a.b, curry, 2) 
lapply(curry.a.b.c, do.call, list()) 

# > [1] 1003 
# > [1] 1003 

这是怎么回事?

+2

'lapply'评估'在一个新的环境FUN'。我认为这与它有关。 – 2012-04-04 22:39:59

+0

我认为答案是一样的,在汤米的回复http://stackoverflow.com/questions/9950144/access-lapply-index-names-inside-fun/9950734#comment12707459_9950734 – 2012-04-05 03:04:07

+0

约书亚是温暖的,科斯克钉它。谢谢你们。 – 2012-04-05 05:51:19

回答

2

fncurry不在功能范围内评估,因此它是promise。 如果你force它,那么你可以得到你所期望的:

curry <- function(fn, ...) { 
    force(fn) 
    arglist <- list(...) 
    function(...) { 
    do.call(fn, append(arglist, list(...))) 
    } 
} 

然后,

> curry.a.b <- lapply(curry.a, curry, 1) 
> curry.a.b[[1]](2) 
[1] 13 
> curry.a.b[[2]](2) 
[1] 1003 
> 
> curry.a.b.c <- lapply(curry.a.b, curry, 2) 
> lapply(curry.a.b.c, do.call, list()) 
[[1]] 
[1] 13 

[[2]] 
[1] 1003 

更多内部,lapply产生的局部变量X由函数每次调用称。如果X在调用lapply时未在每个函数中评估,则X有承诺。在调用lapply,X之后,在来自lapply的所有函数调用中返回相同(即最后一个)值。所以lapply是相似的:

f0 <- function(i) function() i 
f1 <- function(i) {force(i); function() i} 

f <- local({ 
r0 <- list() 
r1 <- list() 
for (i in 1:2) { 
    r0[[i]] <- f0(i) 
    r1[[i]] <- f1(i) 
} 
list(r0 = r0, r1 = r1) 
}) 

然后,

> f$r0[[1]]() 
[1] 2 
> f$r1[[1]]() 
[1] 1 
> f$r0[[2]]() 
[1] 2 
> f$r1[[2]]() 
[1] 2 
+0

100%牛眼。谢谢!我真的认为闭包是承诺,所以我做了闭包< - function(...){do.call(fn,append(arglist,list(...))}; force(闭包); return closure'当然,这并不奏效。 – 2012-04-05 05:49:47

相关问题