2014-09-25 18 views
6
kullanıyorum

iç çevreyi belirtmek do.call aşağıdakifonksiyonu

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

, bir paket içinde inşa ama sadece fonksiyonları bir ise işe yaramaz gerçeğiyle Isırılmışsın farklı (yerel) çerçeve,

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

Ben envir=parent.frame(2)do.call() için (çalışmıyor) geçen denedim; Açıkçası, ?parent.frame yardım sayfasının başım ağrıyor. Daha sağlam bir do.call kullanımı için herhangi bir ipucu?

İşlevler listesinin, başka bir kod parçasından geçirilen bir karakter vektörü olarak geldiğini unutmayın; Fonksiyonları doğrudan geçmemeyi tercih ederim.

Düzenleme: bir daha büküm ... benim oyuncak örnekle sağ sorunu resimli sanıyordum ama kullanıyorum gerçek kod ben içinde fun_wrap1 arıyorum anlamda biraz farklıdır Ayrı bir işlev. Önerilen çözümler bu bağlamda başarısız.

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" 

(ve aynı match.fun yaklaşımla olur)

Ben fun_wrap1 için isteğe bağlı ortam geçirerek işe alabilirsiniz

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

ve bu umutla bu kadar.

+0

Sürekli değişiklikler hakkında üzgünüm, ilk yinelemeyi yazdığımda hedefi doğru bir şekilde tanımlayamadım. – baptiste

+0

Düzeltilen örneğinizde başarısız olursa, yeni işlev şu şekilde değiştirilmelidir: 'fun_wrap1 <- işlev (funs, envir = parent.frame()) { lapply (funs, do.call, args = list (x = 3) , envir = envir) } 'foo' işlevi olduğu gibi kalabilir. –

+0

Teşekkürler, tavsiyenize göre değiştirdim. – baptiste

cevap

5

Bu iş gibi görünüyor, ama ben diğer etkileri ı dikkate değilim varsa emin değilim: Yani bu aslında olarak lapply bildiriye sahip eşdeğerdir

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(
     c('funa1', 'funb1'), 
     function(f) do.call(f, args=list(x=3), envir=environment()) 
    ) 
+0

Çok yoğundum! Çevreyi listeye x = 3'le birlikte koydum ... – baptiste

+0

@baptiste - muhtemelen açık bir şekilde 'args = list (x = 3)' olmalıdır. – thelatemail

2

fun_wrap2'daki işlevleri değerlendirirsek çalışır. Sorudaki yaklaşımla ilgili problem, karakter dizelerinin, arama yolunu değiştiren işlem işlevlerinden birinin içindeki işlevlere dönüştürülmesidir.

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

bu mantıklı, ek açıklama için teşekkürler.O zamandan beri benim sorunumun biraz farklı olduğunu fark ettim ve bu yaklaşımı gerçekten işe koyduğum sürece (bkz. Düzenle) – baptiste

+0

bu yaklaşımı alamıyorum, diğer cevabı kabul ettim, Doğru çevre, sorunun anahtarıydı. match.fun' burada aynı şeyi başardı, ama belki de açıkça değil. – baptiste

0

@ g-grothendieck'in yanıtının biraz daha basit bir sürümü. Fonksiyon isimlerini kullanmak yerine, fonksiyonları sadece lapply'a gönderilen listeye koyarız.

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

Bu benim orijinal cevabımdı ama yorumlarda, girdinin karakterlerin bir karakter vektörü olması gerektiğini, böylece değiştirdiğimi belirtti. –