1

Mathematica 有一种有趣的方式来逐步构建您在复杂计算的各个点计算的结果列表(或多个列表)。我想在 R 中做类似的事情。

Sow在 Mathematica 中,您可以通过将整个计算包装在对函数的调用中来收集计算期间每次调用函数的每个参数的列表Reap。R 是否具有与这些功能等效的功能?您是否可以使用环境和操作员来模拟它<<-,或者范围规则不允许这样做?

编辑:这是一个人为的例子。假设我想产生一个立方体的总和,但我也想收集我用来制作立方体总和的数字的平方。我知道进行这种精确计算可能有更多惯用的方法,但它代表在收集沿途产生的各种物品时得到一些最终答案。

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

我希望它返回具有立方体总和加上包含正方形列表的命名变量“squares”的东西。

4

1 回答 1

6

我尚未对此进行彻底测试,但它似乎适用于您的简单示例。这里我们定义reapsow

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 回答