How can I reference the local environment within a function, in R?
To get the current environment, just call environment()
.
In general, sys.frame
returns any of the environments currently on the call stack, and sys.nframe
returns the current depth of the call stack. sys.frames
returns a list of all environments on the call stack.
environment(f)
returns the closure environment for a function f
(where it will look for functions and global variables).
parent.env(e)
returns the parent environment where it will look if a symbol is not found 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
This will call the local function floc
with a stack depth of 3. It returns a list with the current environment, it's parent (the local environment in f
), and it's grand parent (where f
was defined, so globalenv
). It also returns the list of stack frames (environments). These are the environments for the recursive calls in g
(except the last one which is the current environment of floc
).
Iterator
I noticed that this profile receives views. Let me make your click a little more worthwhile, and explain Iterator's raison d'être... I do some things again and again, or my code does (almost) the same thing again and again. Iterating isn't tedious per se, but it helps to iterate rapidly. I am mastering that. I work on topics in many areas, usually solving stimulating problems with stimulating data. Sometimes there is a stimulating amount of stimulating data. To contact me, look for me in the SO R chat room, where I am often learning from R experts, or leave a message there or in a separate chat (@Iterator) - SO will alert me.
Updated on February 09, 2020Comments
-
Iterator about 4 years
[This question has been resolved in the chat room, by Spacedman, but I'm posting it for others' benefit in the future.]
I have a function,
myFunc
, which createslocalFunc
inside of it. (NB: this is not in a package, but in the global environment.) I'd like to know wherelocalFunc
exists in the search path, as I'd like to analyze it viamvbutils::foodweb
.Here is an example:
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) }
However, a call to
myFunc()
does not seem to indicate thatlocalFunc
callsdata.table()
. This is incorrect - what gives?(NB: The
where
argument specifies the search path.)
Update 1: As Tommy and Spacedman point out, the trick is to specify
environment()
. The call tofoodweb()
refers towhere = c(1, ix)
. The index1
is a mistake. That arose from thinking that.GlobalEnv
, which is often (always?) the first item in thesearch()
vector, is the right place to search. That is erroneous. Instead, one should refer toenvironment()
, and the correct call is below. (NB:ix
specifies the location ofdata.table()
in thesearch()
output.)tmpWeb <- foodweb(where = c(environment(),ix), prune = vecPrune, plotting = FALSE)
This appears in the answer to this question, in a function called
checkScriptDependencies
, which wraps the code from an R script file into a local function, which is then analyzed byfoodweb
. This is a limited example of how to useenvironment()
, and Tommy has given a good explanation of how to use it and similar functions in this context. -
Spacedman over 12 yearsThat's what I said in the chatroom. Now @iterator, give him the tick :)
-
Iterator over 12 years@Spacedman You had your chance. :) Tommy, thanks - your elaboration on what's going on is helpful. I knew the answer from Spacedman's chat comments, but didn't want to make the question self-answering. I was hoping that someone would come along with a more cogent explanation, as you have done.
-
qed almost 11 yearscurEnv is the same as callStack[[3]], parent and grandparent are totally different from the other callStacks, why?
-
Tommy almost 11 yearsCall stacks are the environments of all the callers, but that's NOT where variables are found. The parent environments are used for that - and they are linked together when the function is DEFINED, whereas calls stacks are linked together when the functions are CALLED. Tricky and confusing, I know...