2014-09-25 70 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