2012-01-07 5 views
26

[Questa domanda è stata risolta nel chat room, by Spacedman, ma sto postando per beneficio degli altri in futuro.]Come posso fare riferimento all'ambiente locale all'interno di una funzione, in R?

Ho una funzione, myFunc, che crea localFunc all'interno di esso. (NB: questo non è in un pacchetto, ma nell'ambiente globale.) Mi piacerebbe sapere dove esiste localFunc nel percorso di ricerca, perché mi piacerebbe analizzarlo tramite mvbutils::foodweb.

Ecco un esempio:

myFunc <- function(){ 
    require(data.table) 
    require(mvbutils) 
    localFunc <- function(x){ 
     return(as.data.table(x)) 
    } 

    vecPrune <- c("localFunc",ls("package:data.table")) 
    ix <- match("data.table",search()) 
    tmpWeb <- foodweb(where = c(1,ix), prune = vecPrune, plotting = FALSE) 
    return(tmpWeb) 
} 

Tuttavia, una chiamata a myFunc() non sembra indicare che localFunc chiamate data.table(). Questo non è corretto - cosa dà?

(NB: L'argomento where specifica il percorso di ricerca.)


Update 1: Come Tommy e Spacedman sottolineano, il trucco è di specificare environment(). La chiamata a foodweb() si riferisce a where = c(1, ix). L'indice 1 è un errore. Che nasce dal pensare che .GlobalEnv, che è spesso (sempre?) Il primo elemento nel vettore search(), è il posto giusto per la ricerca. Questo è errato. Invece, si dovrebbe fare riferimento a environment() e la chiamata corretta è di seguito. (NB:. ix specifica la posizione del data.table() nel search() uscita)

tmpWeb <- foodweb(where = c(environment(),ix), prune = vecPrune, plotting = FALSE) 

Questo appare nella risposta alla this question, in una funzione chiamata checkScriptDependencies, che avvolge il codice da un file di script R in una funzione locale, che viene quindi analizzato da foodweb. Questo è un esempio limitato di come utilizzare environment() e Tommy ha fornito una buona spiegazione su come utilizzarlo e funzioni simili in questo contesto.

risposta

34

Per ottenere l'ambiente corrente, è sufficiente chiamare il numero environment().

In generale, sys.frame restituisce uno qualsiasi degli ambienti attualmente presenti nello stack di chiamate e sys.nframe restituisce la profondità corrente dello stack di chiamate. sys.frames restituisce un elenco di tutti gli ambienti nello stack di chiamate.

environment(f) restituisce l'ambiente di chiusura per una funzione f (dove cercherà funzioni e variabili globali).

parent.env(e) restituisce l'ambiente genitore dove apparirà se non viene trovato un simbolo in e.

f <- function() { 
    function() list(curEnv=environment(), parent=parent.env(environment()), 
      grandParent=parent.env(parent.env(environment())), callStack=sys.frames(), 
      callStackDepth=sys.nframe()) 
} 
g <- function(f, n=2) if (n>2) g(f, n-1) else f() 

floc <- f() # generate a local function 
g(floc, 3) # call it 

Questo chiamerà la funzione locale floc con una profondità pila di 3. Si restituisce una lista con il contesto attuale, è genitore (l'ambiente locale in f), ed è nonno (dove è stato definito f, quindi globalenv). Restituisce anche l'elenco dei frame dello stack (ambienti). Questi sono gli ambienti per le chiamate ricorsive in g (tranne l'ultimo che è l'ambiente corrente di floc).

+0

Questo è quello che ho detto nella chat. Ora @iterator, dagli il segno di spunta :) – Spacedman

+0

@Spacedman Hai avuto la tua occasione.:) Tommy, grazie - la tua elaborazione su quello che sta succedendo è utile. Conoscevo la risposta dai commenti della chat di Spacedman, ma non volevo fare la domanda rispondendo da sola. Speravo che qualcuno venisse con una spiegazione più convincente, come hai fatto tu. – Iterator

+0

curEnv è lo stesso di callStack [[3]], genitore e nonno sono totalmente diversi dagli altri callStacks, perché? – qed

Problemi correlati