do.call在函数内部指定环境

问题描述:

我正在包装中使用以下结构,

I'm using the following construct in a package,

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

但是我只是被一个事实咬住了,即如果函数位于不同的(本地)框架中,它将无法正常工作,

but I've just been bitten by the fact that it won't work if the functions are in a different (local) frame,

## 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的提示?

I've tried passing envir=parent.frame(2) to do.call() (doesn't work); frankly the help page of ?parent.frame goes way over my head. Any hint for a more robust use of do.call?

请注意,函数列表是一个字符向量,它是从另一段代码传递过来的;我不想直接传递这些函数.

Note that the list of functions comes as a character vector, passed from another piece of code; I prefer not to pass the functions directly.

还有一个转折...我以为我已经用玩具示例说明了正确的问题,但是在某种意义上,我正在使用的实际代码略有不同. m在单独的函数中调用fun_wrap1.在这种情况下,建议的解决方案将失败.

one more twist... I thought I'd illustrated the right problem with my toy example, but the actual code I'm using is slightly different, in the sense that I'm calling fun_wrap1 within a separate function. The proposed solutions fail in this context.

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来使它工作,

I can get it to work by passing an optional environment to 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()

希望如此.

这似乎可行,但是我不确定是否有其他隐含意义,我不在考虑之中.

This seems to work, but i'm not sure if it has other implications I'm not considering:

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语句设为:

So this is essentially equivalent to having the lapply statement as:

lapply(
       c('funa1', 'funb1'), 
       function(f) do.call(f, args=list(x=3), envir=environment() )
      )