If you define functions, they are all part of the Global Environment
by default.
I wonder, whether there is a way, to set a function's parent environmet to the calling environment (while
runtime - a function might be called in different places!). Thus, in case of nested functions,
it should become possible, to define a variable in only one envrionment and I would expect for an example like
fun1 <- function() {
# variable "my_env" defined only in this environment
subfun() # calls subsubfun()
return(NULL)
}
an output of exists("my_env", different_environments)
like
# [1] "fun1"
# [1] "===="
# [1] TRUE # Only here: "here", in this function
# [1] FALSE
# [1] FALSE
# [1] " subfun"
# [1] " ======"
# [1] FALSE
# [1] TRUE # Only here: "parent environment", in calling function
# [1] FALSE
# [1] " subsubfun"
# [1] " ========="
# [1] FALSE
# [1] FALSE
# [1] TRUE # Only here: "parent-parent environment", in the function calling the function
From the docs ?parent.frame
sys.parent returns the number of the parent frame if n is 1 (the default), the grandparent if n is 2, and so on. See also the ‘Note’.
(...) parent.frame(n) is a convenient shorthand for sys.frame(sys.parent(n)) (implemented slightly more efficiently).Note
Strictly, sys.parent and parent.frame refer to the context of the parent interpreted function. So internal functions (which may or may not set contexts and so may or may not appear on the call stack) may not be counted, and S3 methods can also do surprising things. Beware of the effect of lazy evaluation: these two functions look at the call stack at the time they are evaluated, not at the time they are called. Passing calls to them as function arguments is unlikely to be a good idea.
Some example to start with from here, which does not work, as all functions are part of the global environment.
subfun0 <- function() {
e <- parent.frame()
attr(e, "name") <- "my_env"
assign("my_env", 1,
envir = parent.frame(),
inherits = FALSE, immediate = TRUE)
return(NULL)
}
subsubfun <- function() {
print(" subsubfun")
print(" =========")
print(exists("my_env"))
print(exists("my_env", parent.frame()))
env <- parent.frame()
print(exists("my_env", parent.env(env)))
return(NULL)
}
subfun <- function() {
print(" subfun")
print(" ======")
print(exists("my_env"))
print(exists("my_env", parent.frame()))
env <- parent.frame()
print(exists("my_env", parent.env(env)))
subsubfun()
return(NULL)
}
fun1 <- function() {
print("fun1")
print("====")
subfun0()
print(exists("my_env"))
print(exists("my_env", parent.frame()))
env <- parent.frame()
print(exists("my_env", parent.env(env)))
subfun()
return(NULL)
}
fun1()
(I just realized, that I had a completely wrong picture of "calling environment" in mind and my questions is, could I make "my picture" work in R.)