Home > Software design >  Using R, how to get the name of the current environment THIS within a function
Using R, how to get the name of the current environment THIS within a function

Time:08-17

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.

  • Related