13

The title basically says it all.

If I do this ...

makeActiveBinding("x", function() runif(2), .GlobalEnv)
x
# [1] 0.7332872 0.4707796
x
# [1] 0.5500310 0.5013099

... is there then any way for me to examine x to learn what function it is linked to (and if not, why not)?

(In this case, I'd like to be able to learn that x was defined to be function() runif(2).)

Josh O'Brien
  • 159,210
  • 26
  • 366
  • 455
  • Romain Francois suggested a [patch to R-devel in 2009](https://stat.ethz.ch/pipermail/r-devel/2009-June/053899.html) to modify this behaviour ([see the link to attachment with C code](https://stat.ethz.ch/pipermail/r-devel/attachments/20090629/16a8c41a/attachment.pl)) – Andrie Apr 17 '13 at 21:45
  • @Andrie this patch did not give the binding function, just print that this is indeed an active binding – Romain Francois Apr 17 '13 at 21:57
  • @Andrie Interesting, but IIUC, it still looks like all Romain's patch would do for `str(x)` would be to print (or rather `cat()`) the string "\n". Is that what you see too? – Josh O'Brien Apr 17 '13 at 21:57
  • @RomainFrancois -- Is it your understanding that, short of C-level hacking, the details of the active binding (including the R function it references) are hidden? Is what I'm asking for similar, in its impossibility, to wanting to see the internals of a promise object? (Meaning is it hidden, on purpose?) – Josh O'Brien Apr 17 '13 at 22:02
  • It looks very hidden indeed. – Romain Francois Apr 17 '13 at 22:07
  • @RomainFrancois -- Thanks. Coming from you, I'll take that as an essentially authoritative answer, unless something else gets posted. Appreciate your answering it! – Josh O'Brien Apr 17 '13 at 22:10

1 Answers1

12

With a bit of noodling around in envir.c, I can get this to work:

#include <Rcpp.h>
using namespace Rcpp ;

#define HASHSIZE(x)      LENGTH(x)
#define HASHVALUE(x)    TRUELENGTH(x)

// [[Rcpp::export]]
SEXP get_binding_fun( std::string name, Environment env){
    SEXP symbol = Rf_install( name.c_str() );
    SEXP tab = HASHTAB(env) ;
    SEXP c = PRINTNAME(symbol);

    // finding the hash code for the symbol
    int hashcode = HASHVALUE(c) % HASHSIZE(tab);

    // get the value there from the hash table
    SEXP res = CAR( VECTOR_ELT(tab, hashcode ) ) ;

    return res ;
}

Save this into a .cpp file, sourceCpp it and use it with this R code:

> makeActiveBinding("x", function() runif(2), .GlobalEnv)
> get_binding_fun("x", .GlobalEnv)
# function ()
# runif(2)
Romain Francois
  • 17,432
  • 3
  • 51
  • 77