It looks like you can have one function pass data back transparently to a parent function with the assign
operation.
Example (Setup)
calling = function()
{
a = 25;
cat("\n ...CALLING... a = ", a, "\n");
assign("a", a, envir=parent.frame(1) ); # ?sys.calls
}
caller = function()
{
a = 15;
cat("\n ...CALLER... a = ", a, "\n");
pf = parent.frame(); ## how to say THIS current FRAME
cat("\n ...CALLER_FRAME... pf = \n");
print(pf);
cat("\n\n\n");
calling();
cat("\n ...CALLER*... a = ", a, "\n");
}
RUN
a = 5;
cat("\n ...GLOBAL... a = ", a, "\n");
caller();
# scope, should mess with GLOBAL = 5
cat("\n ...GLOBAL*... a = ", a, "\n");
OUTPUT
> a = 5;
> cat("\n ...GLOBAL... a = ", a, "\n");
...GLOBAL... a = 5
> caller();
...CALLER... a = 15
...CALLER_FRAME... pf =
<environment: R_GlobalEnv>
...CALLING... a = 25
...CALLER*... a = 25
> # scope, should mess with GLOBAL = 5
> cat("\n ...GLOBAL*... a = ", a, "\n");
...GLOBAL*... a = 5
Question
So above, the GLOBAL a
was not altered, but calling
was able to update the value of a
for caller
without returning the value. That is, calling
passed back the value to caller
with assign
.
The question is in the code, in caller
, how do I get THIS current frame reference?
How could I use that if I had more complicated nesting? Pass envir
to calling
that may have been a few functions deep? This reference Can you pass-by-reference in R? has some discussion, but I don't fully under THIS current frame reference of caller
?
CodePudding user response:
As @zephryl said, environment()
returns the currently active environment. You could write your calling()
function like this:
calling <- function(envir = parent.frame()) {
a <- 25
assign("a", a, envir = envir)
}
and then it would by default assign in the caller, but if you specified the envir
argument it could assign there instead.
Then you could do something like this:
myenv <- new.env()
calling(envir = myenv)
myenv$a
#> [1] 25
to do the assignment in a custom environment. And if you wrote caller()
like this:
caller <- function() {
a <- 2
calling(envir = environment())
cat("in caller, a=", a, "\n")
}
a <- 1
caller()
#> in caller, a= 25
print(a)
#> [1] 1
it would work just like
caller2 <- function() {
a <- 3
calling()
cat("in caller2, a=", a, "\n")
}
a <- 4
caller2()
#> in caller2, a= 25
print(a)
#> [1] 4
because while evaluating caller()
, environment()
gives a reference to the active environment, and while evaluating calling()
, parent.frame()
points to the environment of the caller, which would be the same thing.