Skip to content

creating environments in package's C code

9 messages · Martin Becker, Jeffrey Horner, Simon Urbanek +2 more

#
Dear developers,

is it possible to create environments in C code of packages?
Simply using
  SEXP env;
  PROTECT (env  = allocSExp(ENVSXP));
and assigning the enclosing environment with SET_ENCLOS seems to be 
insufficient.

Best wishes,

  Martin
#
Martin Becker wrote:
Here's a function I use in rapache to create one:

static SEXP NewEnv(SEXP enclos){
     SEXP env;
     PROTECT(env = allocSExp(ENVSXP));

     SET_FRAME(env, R_NilValue);
     SET_ENCLOS(env, (enclos)? enclos: R_GlobalEnv);
     SET_HASHTAB(env, R_NilValue);
     SET_ATTRIB(env, R_NilValue);

     UNPROTECT(1);

     return env;
}


and an example that creates a new environment and then assigns a 
variable named OK an integer vector length 1 with value 0:

SEXP env = NewEnv(R_GlobalEnv);
defineVar(install("OK"),NewInteger(0),env);

Best

Jeff
#
On Oct 1, 2009, at 11:33 , Martin Becker wrote:

            
Rf_NewEnvironment is the function that does it, e.g.,
Rf_NewEnvironment(R_NilValue, R_NilValue, parent)
it's not part of the official API (headers) but it is visible.
For hashed environments it's R_NewHashedEnv().

Cheers,
Simon
#
Jeff Horner wrote:
Oops! I forgot the definition of my simple function NewInteger:

static SEXP NewInteger(int i){
     SEXP val;
     PROTECT(val = NEW_INTEGER(1));
     INTEGER_DATA(val)[0] = i;
     UNPROTECT(1);
     return val;
}
#
Jeff,
On Oct 1, 2009, at 12:37 , Jeff Horner wrote:

            
eek ... that some dangerous bit of code ;). I think Rf_NewEnviroment  
is safer even if it's not the headers :P.
I suspect you like reinventing the wheel ;). Your NewInteger is part  
of the R API and is called ScalarInteger(). When you need something,  
chances are that R has it already, so it's worth greping through the  
headers (and sometimes even through the main sources).

Cheers,
Simon
#
On 10/1/2009 12:37 PM, Jeff Horner wrote:
One comment:  I would protect the env, because install() and 
NewInteger() could each trigger a garbage collection.  That is, use

SEXP env;
PROTECT(env = NewEnv(R_GlobalEnv));
defineVar(install("OK"),NewInteger(0),env);
UNPROTECT(1);

Duncan Murdoch
#
Simon Urbanek wrote:
Interesting. I know that I patterned that function after some grepping 
for ENVSXP, probably src/main/serialize.c's ReadItem() as it's similar. 
Plus I only used what was available from the public headers.

So, if Rf_NewEnviroment is the right way to do it then make it public ;P.
Yes, that I created NewInteger is a grave oversight on my part. It's 
been around since R's first release (if my svn log research was 
correct). Thanks. I'm putting it on rapache's TODO list to take it out.

Jeff
1 day later
#
Simon Urbanek wrote on 10/01/2009 11:51 AM:
[...]
I am reminded of what Robert Gentleman said at DSC 2005 during the R/S 
round-chair discussion: "Brian Ripley is the only one I know who keeps R 
in his frontal lobe."

I can only aspire to such greatness, Simon.

Jeff
#
I hope you will forgive a serious comment on this thread, but the 
new "sos" package makes "greping through the headers" shockingly easy.  
It returns the 'RSiteSearch( ___ , "function")' information in a 
data.frame of class "findFn" sorted to put the package with the most 
matches first.  Duncan Murdoch wrote a "???" alias for this "findFn" 
function.  Union and intersection operators are defined for 
"findFn"objects.  The "findFn2xls" function writes an Excel file with 
three sheets giving an extended package summary, the matches (including 
the URLs), and the call.  An article on this is scheduled to appear in 
the next issue of "R Journal" and is available now via vignette('sos'). 


      This "sos" package is not as good as greping Ripley's frontal 
lobe, but it makes it quite easy to do a literature search of all 
contributed R packages. 


      Spencer
Jeffrey Horner wrote: