2013-07-18 16 views
5

Próbuję uruchomić fragment kodu R w trybie piaskownicy, ładując wszystkie niezbędne zależności (funkcje i dane) do nowego środowiska i oceniając wyrażenie w tym obszarze środowisko. Jednak mam problemy z funkcjami wywołującymi inne funkcje w środowisku. Oto prosty przykład:R - Ocena zagnieżdżonej funkcji w środowisku

jobenv <- new.env(parent=globalenv()) 
assign("f1", function(x) x*2, envir=jobenv) 
assign("f2", function(y) f1(y) + 1, envir=jobenv) 
expr <- quote(f2(3)) 

Korzystanie eval na expr nie od f2 nie może znaleźć f1

> eval(expr, envir=jobenv) 
Error in f2(3) : could not find function "f1" 

natomiast wyraźnie mocowania środowisko działa

> attach(jobenv) 
> eval(expr) 
[1] 7 

jestem prawdopodobnie brakuje czegoś oczywiste, ale nie mogłem znaleźć żadnej permutacji połączenia eval, które działa. Czy istnieje sposób na uzyskanie tego samego efektu bez dołączania do środowiska?

+1

Należy dokonać edycja nowe pytanie, ponieważ jest bardzo inny niż oryginalny. –

+0

Dzięki za sugestię, zrobiłem, oto ona: [R - ocenia zagnieżdżone wywołanie funkcji w deserializowanym środowisku] (http://stackoverflow.com/questions/17733323/r-evaluate-nested-function-call-in- a-deserialized-environment) –

Odpowiedz

7

Istnieje szereg sposobów w ten sposób, ale trochę jak ten:

jobenv <- new.env(parent=globalenv()) 

local({ 
    f1 <- function(x) x*2 
    f2 <- function(y) f1(y) + 1 
}, envir=jobenv) 

## Check that it works 
ls(jobenv) 
# [1] "f1" "f2" 
local(f2(3), envir=jobenv) 
# [1] 7 
eval(quote(f2(3)), envir=jobenv) 
# [1] 7 
+1

+1 bardzo ładne. Choć można go skrócić i uczynić bardziej ogólnym, umieszczając obie definicje funkcji w jednym "lokalnym" wywołaniu. –

+0

@JoshuaUlrich - Dobry punkt. Dzięki.(Zmieniono moją odpowiedź, aby uwzględnić Twoją sugestię.) –

4

Zasięg jest definiowany, gdy funkcja jest tworzona, a nie po jej wywołaniu. Zobacz instrukcję section 10.7 of the Introduction to R.

Wydaje mi się to nieco dziwne, ale zachowujesz się tak samo, nawet jeśli unikasz razem assign i po prostu używasz $<-.

jobenv <- new.env(parent=globalenv()) 
jobenv$f1 <- function(x) x*2 
jobenv$f2 <- function(y) f1(y) + 1 
expr <- quote(f2(3)) 
eval(expr, envir=jobenv) 

To wydaje się być fakt, że środowisko zakrywające od f1 i f2 jest globalnym środowisku. Spodziewałbym się, że będzie to jobenv.

> environment(jobenv$f1) 
<environment: R_GlobalEnv> 
> environment(jobenv$f2) 
<environment: R_GlobalEnv> 

Jednym rozwiązaniem jest jawne ustawienie środowiska dla każdej funkcji ... ale musi istnieć łatwiejszy sposób.

> environment(jobenv$f1) <- jobenv 
> environment(jobenv$f2) <- jobenv 
> eval(expr, envir=jobenv) 
[1] 7 
+0

+1 dla 'inherits = TRUE'. Muszę jednak wyznać, że nie widzę, jak zmienna '" f1 "' znajduje się w 'jobenv' przed jej pierwszym przypisaniem. Z cytowanego fragmentu oczekiwałbym, że symbol, nie napotkany w tym miejscu, zostanie przypisany do przestrzeni roboczej użytkownika. –

+0

Wygląda na to, że miałem rację, będąc sceptycznym: twój pierwszy przykład po prostu przypisuje 'f1' i' f2' do globalnego środowiska. (Wypróbuj 'ls()' i 'ls (jobenv)' po uruchomieniu.) A twój drugi przykład też nie działa. –

+0

@ JoshO'Brien: masz rację. F- –

Powiązane problemy