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

Douglas Bates bates at stat.wisc.edu
Fri May 21 13:42:56 CEST 2010


On Fri, May 21, 2010 at 3:18 AM, Romain Francois
<romain.francois at dbmail.com> wrote:
>
> 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.

Yes, it does fix the problem.  As always thanks for the speedy
response and code fix.

> 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
>
>
> _______________________________________________
> Rcpp-devel mailing list
> Rcpp-devel at lists.r-forge.r-project.org
> https://lists.r-forge.r-project.org/cgi-bin/mailman/listinfo/rcpp-devel
>


More information about the Rcpp-devel mailing list