2013-10-17 33 views
3

我想弄清楚如何获得R的callCC函数,用于短路评估一个函数以评估函数,如lapply和Reduce。在R中使用具有高阶函数的callCC

动机

这将使减少和和lapply具有渐近效率> O(N),允许您 出口计算的早期。例如,如果我在列表中搜索一个值,我可以在列表中映射'finder'函数,第二个函数会发现lapply停止运行并返回该值(就像打破循环一样,或者使用return语句提前突破)。

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

说我想写一个函数来查找列表中的值“100”:东西相当于

imperativeVersion <- function (xs) { 
    for (val in xs) if (val == 100) return (val) 
} 

功能传递给lapply会是什么样子:

find100 <- function (val) { if (val == 100) SHORT_CIRCUIT(val) } 
functionalVersion <- function (xs) lapply(xs, find100) 

由于尚未定义短路功能,这(明显)崩溃。

callCC(function (SHORT_CIRCUIT) lapply(1:1000, find100)) 

问题是,这也会崩溃,因为当find100被定义时,短路功能不在。我想要类似这样的工作。

以下工作,因为SHORT_CIRCUIT是在传递给lapply的函数被创建时定义的。

callCC(
    function (SHORT_CIRCUIT) { 
     lapply(1:1000, function (val) { 
      if (val == 100) SHORT_CIRCUIT(val) 
     }) 
) 

我怎样才能让SHORT_CIRCUIT传入而不定义它内嵌像上面lapply的功能来定义?

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

如果我含糊不清或需要澄清,请在下面留言。我希望有人可以帮助这个:)

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

回答

1

我发现了一个soluton这个问题:

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)) 

诀窍使高阶函数一起工作callCC将在继续执行程序的其余部分之前将短路功能分配到输入功能环境中。我做了一个克隆环境,以避免意想不到的副作用。

0

我不知道,如果它可以使用的,但是:

find100 <- "function (val) { if (val == 100) SHORT_CIRCUIT(val) }" 
    callCC(function (SHORT_CIRCUIT) lapply(1:1000, eval(parse(text = find100)))) 
    #[1] 100 
+0

感谢您的回答,但对于我的目的,evalparse对于hacky方面太过分了。将函数解析为字符串并不总是可能的,并且关于该函数被定义的封装环境的所有信息都将丢失。 (这会打破许多功能)。 – RyanGrannell