在R中使用具有高阶函数的callCC

Rya*_*ell 5 continuations functional-programming r

我试图弄清楚如何获得R的callCC函数来短路函数的评估,以便与lapply和Reduce等函数一起工作.

动机

这将使Reduce和lapply具有渐近效率> O(n),允许您提前退出计算.

例如,如果我在列表中搜索一个值,我可以在列表中映射一个'finder'函数,第二个找到lapply停止运行并返回该值(就像打破一个循环,或者使用一个返回声明提前爆发).

问题是我在使用callCC需要的样式编写lapply和Reduce应该使用的函数时遇到问题.

假设我正在尝试编写一个函数来在列表中找到值'100':相当于

imperativeVersion <- function (xs) {
    for (val in xs) if (val == 100) return (val)
}
Run Code Online (Sandbox Code Playgroud)

传递给lapply的函数如下所示:

find100 <- function (val) { if (val == 100) SHORT_CIRCUIT(val)  }
functionalVersion <- function (xs) lapply(xs, find100)
Run Code Online (Sandbox Code Playgroud)

这(显然)崩溃,因为短路功能尚未定义.

callCC( function (SHORT_CIRCUIT) lapply(1:1000, find100) )
Run Code Online (Sandbox Code Playgroud)

问题是这也会崩溃,因为当定义了find100时,短路功能并不存在.我想要类似的东西工作.

以下是有效的,因为SHORT_CIRCUIT是在创建传递给lapply的函数时定义的.

callCC(
    function (SHORT_CIRCUIT) {
        lapply(1:1000, function (val) {
             if (val == 100) SHORT_CIRCUIT(val)
        })
)
Run Code Online (Sandbox Code Playgroud)

如何在传递给lapply的函数中定义SHORT_CIRCUIT而不像上面那样定义内联?

我知道这个例子可以使用循环,减少或任何其他方式来实现.我正在寻找解决使用callCC与lapply和Reduce的具体问题的解决方案.

如果我含糊不清或需要任何澄清,请在下面留言.我希望有人可以帮忙:)

编辑一:方法应该是'生产质量'; 没有贬值功能或类似的黑魔法.

Rya*_*ell 3

我找到了解决这个问题的方法:

find100 <- function (val) {
    if (val == 100) SHORT_CIRCUIT(val)
}

short_map <- function (fn, coll) {


    callCC(function (SHORT_CIRCUIT) {

        clone_env <- new.env(parent = environment(fn))
        clone_env$SHORT_CIRCUIT <- SHORT_CIRCUIT

        environment(fn) <- clone_env
        lapply(coll, fn)

    })
}

short_map(find100, c(1,2,100,3))
Run Code Online (Sandbox Code Playgroud)

让高阶函数与 callCC 一起工作的技巧是在继续程序的其余部分之前将短路函数分配到输入函数环境中。我克隆了环境以避免意外的副作用。