1

Mathematica には,複雑な計算のさまざまなポイントで計算する結果のリスト(または複数のリスト)を段階的に構築する興味深い方法があります.Rで似たようなことをしたいです。

SowMathematica では、計算全体を関数の呼び出しにラップすることにより、計算中に関数の呼び出しごとに各引数のリストを収集できReapます。Rにはこれらの機能に相当するものがありますか? おそらく環境とオペレーターでそれをエミュレートできますか<<-、それともスコープ規則で許可されませんか?

編集:これは不自然な例です。立方体の合計を生成したいが、立方体の合計を作成するために使用した数値の 2 乗も収集したいとします。この正確な計算を行うにはもっと慣用的な方法があるかもしれませんが、途中で生成されたさまざまなアイテムを収集しながら最終的な答えを得ることを表しています。

reap(sum(sapply(1:100, function(i) { sow(squares = i * i); i * i * i }))

これは、立方体の合計と、正方形のリストを含む名前付き変数「正方形」を含むものを返すようにしたいと思います。

4

1 に答える 1

6

これを完全にテストしたわけではありませんが、単純な例ではうまくいくようです。ここで定義reapし、sow

reap <- function(...) {
    expr <- substitute(...)
    REAPENV <- new.env()
    parent.env(REAPENV) <- parent.frame()
    x <- eval(expr, REAPENV)
    c(list(x), as.list(REAPENV))
}

sow <- function(...) {
    expr <- substitute(alist(...))[-1]
    for( f in rev(sys.frames())) {
        if(exists("REAPENV", envir=f)) {
            re <- get("REAPENV", envir=f)
            if (is.null(names(expr))) {
                names(expr) <- if(length(expr)==1) {"sow"} else {letters[1:length(expr)]}
            }
            stopifnot(all(nchar(names(expr))!=0))
            for(n in names(expr)) {
                sx <- eval(expr[[n]], parent.frame())
                cv <- if(exists(n, envir=re, inherits=FALSE)) {get(n, envir=re)} else {list()}
                if(length(cv)>0) {
                    assign(n, append(cv, sx), envir=re)
                } else {
                    assign(n, sx, envir=re)
                }
            }
            break;
        }
    }
    invisible(NULL)
}

したがって、reap()関数は基本的に新しい環境を定義し、そのコンテキスト内でその引数を呼び出すだけです。このsow関数は、名前付きパラメーター リストを受け取り、そのパラメーターを評価して、最も近い囲みの "reap" 環境に割り当てます。最後にreap()、最初の要素として渡された式の「自然な」戻り値を持つリストを返し、呼び出し中に使用された名前に対応する名前付き要素を追加しsow()ます。だからあなたが走るなら

reap(sum(sapply(1:5, function(i) { sow(squares=i * i); i * i * i; })))

あなたが得る

[[1]]
[1] 225

$squares
[1]  1  4  9 16 25

前述したように、これは単純なテスト ケースで機能するようです。正しい作業リーピング環境を見つけて割り当てるには、改善を加えることができると確信しています。しかし、少なくともこのようなことを追求したい場合は、これが出発点になるかもしれません。

于 2014-09-07T04:34:18.013 に答える