6

我在一个包中使用以下构造,

## two functions in the global environment
funa <- function(x) x^2
funb <- function(x) x^3
## called within a function, fine
fun_wrap <- function(){
  lapply(c('funa', 'funb'), do.call, list(x=3))
}

fun_wrap()
[[1]]
[1] 9

[[2]]
[1] 27

但我刚刚被这样一个事实所困扰,即如果函数位于不同的(本地)框架中,它将无法工作,

## same construct, but the functions are local
fun_wrap1 <- function(){
  funa1 <- function(x) x^2
  funb1 <- function(x) x^3
  lapply(c('funa1', 'funb1'), do.call, list(x=3))
}
## now it fails
fun_wrap1()
##Error in FUN(c("funa1", "funb1")[[1L]], ...) : 
##  could not find function "funa1"

我试过传递envir=parent.frame(2)do.call()(不起作用);坦率地说,帮助页面?parent.frame超出了我的想象。有什么提示可以更强大地使用 do.call 吗?

请注意,函数列表以字符向量的形式出现,从另一段代码传递过来;我不喜欢直接传递函数。

编辑:还有一个转折......我认为我已经用我的玩具示例说明了正确的问题,但我使用的实际代码略有不同,因为我fun_wrap1在单独的函数中调用。建议的解决方案在这种情况下失败了。

fun_wrap1 <- function(funs){
  lapply(funs, do.call, args=list(x=3), envir=environment())
}

foo <- function(){
  funa1 <- function(x) x^2
  funb1 <- function(x) x^3
 fun_wrap1(c('funa1', 'funb1'))
}

foo()
##Error in FUN(c("funa1", "funb1")[[1L]], ...) : 
##  could not find function "funa1"

(这种match.fun方法也会发生同样的情况)

我可以通过将可选环境传递给它来使其工作fun_wrap1

fun_wrap1 <- function(funs, e=parent.frame()){
  lapply(funs, do.call, args=list(x=3), envir=e)
}

foo <- function(){
  funa1 <- function(x) x^2
  funb1 <- function(x) x^3
  fun_wrap1(c('funa1', 'funb1'))
}

foo()

希望就是这样。

4

3 回答 3

5

这似乎可行,但我不确定它是否有其他我没有考虑的影响:

fun_wrap1 <- function(){
  funa1 <- function(x) x^2
  funb1 <- function(x) x^3
  lapply(c('funa1', 'funb1'), do.call, args=list(x=3), envir=environment())
}

fun_wrap1()
#[[1]]
#[1] 9
#
#[[2]]
#[1] 27

所以这本质上等同于将lapply语句设置为:

lapply(
       c('funa1', 'funb1'), 
       function(f) do.call(f, args=list(x=3), envir=environment() )
      ) 
于 2014-09-25T00:43:34.113 回答
2

显然,如果我们评估其中的功能是fun_wrap2可行的。问题中的方法的问题是字符串被转换为更改查找路径的处理函数之一内的函数。

fun_wrap2 <- function(){

  funa1 <- function(x) x^2
  funb1 <- function(x) x^3

  nms <- c("funa1", "funb1")
  funs <- lapply(nms, match.fun)
  lapply(funs, do.call, list(x=3))

}

fun_wrap2()
于 2014-09-25T00:32:14.710 回答
0

@g-grothendieck 答案的稍微简单的版本。我们不使用函数名称,而是将函数本身放入馈送到的列表中lapply

fun_wrap1 <- function(){
  funa1 <- function(x) x^2
  funb1 <- function(x) x^3
  lapply(list(funa1, funb1), do.call, list(x=3))
}

fun_wrap1()
于 2014-09-25T00:36:11.997 回答