2014-09-25 67 views
6

我使用指定的环境下构建一个包,do.call内部功能

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

,这就是希望它。

+0

对于不断变化的抱歉,我在编写第一次迭代时未能正确识别目标。 – baptiste 2014-09-25 01:06:25

+0

在您的修改失败的示例中,应将新函数更改为:fun_wrap1函数(funs,envir = parent.frame())lapply(funs,do.call,args = list(x = 3) ,envir = envir) }'foo'函数可以保持原样。 – 2014-09-25 01:13:23

+0

谢谢,我根据你的建议改变了它。 – baptiste 2014-09-25 01:18:21

回答

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()) 
    ) 
+0

我当时非常密集!我把环境放在'x = 3'旁边的列表中...... – baptiste 2014-09-25 00:45:42

+0

@baptiste - 它应该可能是'args = list(x = 3)'是非常明确的。 – thelatemail 2014-09-25 00:48:22

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() 
+0

这是有道理的,谢谢你的补充说明。我已经意识到我的问题虽然略有不同,但我无法在那里使用这种方法(请参阅编辑) – baptiste 2014-09-25 01:08:06

+0

,而我真的很感谢帮助,我接受了其他答案,因为它澄清了明确的通过正确的环境,这是问题的关键。 'match.fun'在这里也达到了同样的效果,但可能并不那么明确。 – baptiste 2014-09-25 01:22:57

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() 
+0

这是我的原始答案,但他在评论中指出,输入必须是名称的字符向量,所以我改变了它。 – 2014-09-25 00:37:02