5

一連の呼び出しを使用して、理想的には最後の呼び出しで最終的な目的の値を返すlapplyカリー化された関数のリストを作成しようとしています。lapplyカリー化は機能しますがlapply、2 番目のアプリケーションの後に常にリストの最後の要素を適用するようです。

例:

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

「スコープlapplyを壊す」の次:curry

# 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

curryorrcurry関数の結果とは思えません。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

何が起きてる?

4

1 に答える 1

2

fnincurryは function のスコープで評価されないため、 です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場合は、約束です。を呼び出した後、すべての関数呼び出しで fromは同じ (つまり、最後の) 値を返します。同様に、次のようになります。XlapplyXlapplyXlapplylapply

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
于 2012-04-05T04:48:56.313 に答える