2014-09-25 2 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?

Обратите внимание, что список функций поступает как вектор символов, переданный из другого фрагмента кода; Я предпочитаю не передавать функции напрямую.

Edit: еще один поворот ... Я думал, что я проиллюстрировал правильно проблему с моей игрушкой, например, но фактический код, я использую немного отличается, в том смысле, что я звоню 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

+0

В вашем пересмотренном примере, который терпит неудачу, новая функция должна быть изменена на: 'fun_wrap1 <- function (funs, envir = parent.frame()) { lapply (funs, do.call, args = list (x = 3) , envir = envir) } 'Функция' foo' может оставаться такой, какая есть. –

+0

Спасибо, я изменил его в соответствии с вашим советом. – baptiste

ответ

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

+0

@baptiste - вероятно, это будет' args = list (x = 3) ', чтобы быть действительно явным. – thelatemail

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

+0

, в то время как я действительно ценю помощь, я принял другой ответ, поскольку он разъяснил явное прохождение правильная среда, которая была ключевой для проблемы. 'match.fun' достигли того же самого здесь, но, возможно, не так явно. – baptiste

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

Это был мой оригинальный ответ, но он указал в комментариях, что вход должен быть символьным символом имен, поэтому я его изменил. –

 Смежные вопросы

  • Нет связанных вопросов^_^