Search code examples
rrcppscoping

Rcpp scoping of free variables


Say that I have a C++ function dosomething(z) that has a single input variable z, but also a "free" variable located within it (say y). I want to be able to design the scoping so that when I run the Rcpp function, it finds the free variable within the R function in which it is called.

function(x) {
y = x^2
Rcpp::sourceCpp('C:/Users/xxx/dosomething.cpp')
dosomething(z)
}

So in the above, I want the dosomething(z) function to use the value of y defined within the R function? How do I use Rcpp's Environment capabilities to achieve this? At present I can only seem to get free variables working by finding them in the global environment (not directly within the R function).


Solution

  • Rcpp does not have something to directly deal with this, but you could query the frames with sys.frames from within the C++ function (you just have to know that Rcpp adds 7 frames just to call sys.frames), e.g:

    #include <Rcpp.h>
    using namespace Rcpp ;
    
    Environment get_calling_env(){
        Function sys_frames( "sys.frames" ) ;
        List frames = sys_frames() ;
    
        Environment parent = frames.size() == 7 ? R_GlobalEnv : frames[ frames.size() - 8 ] ;
        return parent ;      
    }
    
    // [[Rcpp::export]]
    CharacterVector foo(){   
        Environment parent = get_calling_env() ;
        return parent.ls(false) ;
    }
    

    get_calling_env gives you the environment from where the function was called. So that we can for example get the list of variables from that environment:

    > f <- function(){ y <- 2; foo() }
    # called from a function that calls foo, we get y
    > f()
    [1] "y"
    # if called from the top, we just get the global env
    > foo()
    [1] "f"   "foo"