[Rcpp-devel] Evaluating a call in a particular environment

Romain Francois romain.francois at dbmail.com
Fri May 21 10:18:35 CEST 2010


Le 21/05/10 09:21, Romain Francois a écrit :
>
>
> Le 21/05/10 08:18, Dirk Eddelbuettel a écrit :
>>
>>
>> On 20 May 2010 at 16:54, Douglas Bates wrote:
>> | A short version of this question is "can I evaluate an Rcpp::Language
>> | instance in an Rcpp::Environment instance"? Initially I thought this
>> | was a given but on looking closer at the unit tests I don't see how
>> | exactly it would be done.
>
> Language has this:
>
> /**
> * eval this call in the requested environment
> */
> SEXP eval(SEXP env) ;
>
> And Rcpp::Environment is convertible to SEXP
>
>> | A second short version of this question is "could someone, probably
>> | Romain, remind me what is done to activate the debugging code in Rcpp
>> | or point me to the documentation for it?".
>>
>> Two simple macros are in RcppCommon.h:
>>
>> // simple logging help
>> #define RCPP_DEBUG_LEVEL 0
>>
>> #ifndef logTxt
>> #if RCPP_DEBUG_LEVEL> 0
>> #define logTxt(x) ::logTxtFunction(__FILE__, __LINE__, x);
>> #else
>> #define logTxt(x)
>> #endif
>> #endif
>>
>> #if RCPP_DEBUG_LEVEL> 0
>> #define RCPP_DEBUG( fmt , ... ) Rprintf( "%s:%d " fmt "\n" , __FILE__,
>> __LINE__,##__VA_ARGS__ ) ;
>> #else
>> #define RCPP_DEBUG( fmt , ... )
>> #endif
>>
>> So by flipping RCPP_DEBUG_LEVEL from 0 to 1 or greater you get
>> these. logTxtFunction is in RcppCommon.cpp:
>>
>> void logTxtFunction(const char* file, const int line, const char*
>> expression) {
>> Rprintf("%s:%d %s\n", file, line, expression);
>> }
>>
>> That was the easy part. I think I pass on the long version... That
>> looks a
>> little hairy and I am only one coffee into the day...
>>
>> Dirk
>>
>>
>> | The long version follows:
>> |
>> | In the lme4a package (only on R-forge and requiring the R-forge
>> | version of the Matrix package) the nlmer function to fit nonlinear
>> | mixed-effects models has a nonlinear model, expressed as a call, and
>> | an environment in which to evaluate this call. The operation of
>> | evaluating the deviance of the model involves changing the contents of
>> | some numeric vectors in this environment then evaluating the call.
>> |
>> | The nlmerResp class is declared (in lme4a/src/mer.h) as
>> | class nlmerResp : public rwResp {
>> | Rcpp::Environment nlenv;
>> | Rcpp::Language nlmod;
>> | Rcpp::CharacterVector pnames;
>> | public:
>> | nlmerResp(Rcpp::S4 xp);
>> | void updateMu(Rcpp::NumericVector const&gamma);
>> | };
>> |
>> | and initialized from an Rcpp::S4 object. I have some debugging code
>> | in the current version of the updateMu method to check that the values
>> | in the environment are what I expect them to be
>> |> nm1<- lme4a:::nlmer2(circumference ~ SSlogis(age, Asym, xmid, scal)
>> ~ 0 + Asym + xmid + scal + (0 + Asym|Tree), Orange, start = c(Asym =
>> 200, xmid = 725, scal = 350))
>> |> .Call("nlmerDeEval", nm1)
>> | past initialization of nlmerDe object
>> | gamma after offset: 0, 0, 0, 0, 0
>> | u: 0, 0, 0, 0, 0
>> | b: 0, 0, 0, 0, 0
>> | gamma after reUpdate: 0, 0, 0, 0, 0
>> | gamma after feUpdate: 200, 200, 200, 200, 200
>> | gamma in resp::updateMu: 200, 200, 200, 200, 200
>> | p = 0, parameter name = Asym
>> | current: 200, 200, 200, 200, 200
>> | updated: 200, 200, 200, 200, 200
>> | p = 1, parameter name = xmid
>> | current: 725, 725, 725, 725, 725
>> | updated: 725, 725, 725, 725, 725
>> | p = 2, parameter name = scal
>> | current: 350, 350, 350, 350, 350
>> | updated: 350, 350, 350, 350, 350
>> |
>> | Before evaluation
>> | Error in cpp_exception(message = "object 'xmid' not found", class =
>> | "Rcpp::eval_error") :
>> | object 'xmid' not found
>> |
>> | So I am a bit surprised at xmid not being found because I just
>> | modified it. The objects at the R level are
>> |
>> |> nm1 at resp@nlmod
>> | SSlogis(age, Asym, xmid, scal)
>> |> class(nm1 at resp@nlmod)
>> | [1] "call"
>> |> ls.str(nm1 at resp@nlenv)
>> | age : num [1:35] 118 484 664 1004 1231 ...
>> | Asym : num [1:35] 200 200 200 200 200 200 200 200 200 200 ...
>> | scal : num [1:35] 350 350 350 350 350 350 350 350 350 350 ...
>> | xmid : num [1:35] 725 725 725 725 725 725 725 725 725 725 ...
>> |
>> | and I can evaluate the call in R
>> |
>> |> head(eval(nm1 at resp@nlmod, nm1 at resp@nlenv))
>> | [1] 30.00804 66.87019 91.30771 137.87260 161.86760 172.79186
>> |
>> | I am trying to evaluate the call in the C++ code as
>> |
>> | NumericVector rr = nlmod.eval(nlenv);
>> |
>> | which, I assume, expands to
>> |
>> | NumericVector rr = nlmod.eval(SEXP(nlenv));
>> |
>> | Is there some trick I am missing?
>
> Ah. There might be a problem then:
>
> require( Rcpp )
>
> fx <- cppfunction( signature(x = "environment" ), '
> Environment env(x) ;
> Language call( "sum", Symbol("y") ) ;
> Rf_PrintValue( call ) ;
> return call.eval( env ) ;
> ' )
>
> e <- new.env()
> e[["y"]] <- 1:10
> fx(e)
>
> gives me :
>
>  > fx(e)
> sum(y)
> Erreur dans fx(e) : objet 'y' introuvable
>
> Not sure what the problem is.

I am amazed that apparently we never tested this feature. We do good on 
coverage, but not good enough.

The problem was evaluating an expression too early and should be fixed 
as of rev 1302, and tested by test.Language.in.env. Please test it with 
Matrix/lme4a to see if this fixes the original problem. If you can think 
of additional tests, please include them.

This is serious enough to trigger an emergency release of Rcpp 0.8.1

Romain

-- 
Romain Francois
Professional R Enthusiast
+33(0) 6 28 91 30 30
http://romainfrancois.blog.free.fr
|- http://bit.ly/bklUXt : RcppArmadillo 0.2.1
|- http://bit.ly/936ck2 : Rcpp 0.8.0
`- http://bit.ly/9aKDM9 : embed images in Rd documents




More information about the Rcpp-devel mailing list