[Rcpp-devel] Yet Another Design Question

Douglas Bates bates at stat.wisc.edu
Tue Apr 13 15:16:22 CEST 2010


On Tue, Apr 13, 2010 at 1:14 AM, Romain Francois
<romain at r-enthusiasts.com> wrote:
> Le 13/04/10 00:14, Douglas Bates a écrit :
>>
>> One of the advantages of using S4 classes and methods in R is that
>> there are formal definitions of classes.  I plan eventually to write R
>> code that will take an S4 class definition and create a C++ class
>> definition and constructor code to mirror the R class using Rcpp
>> templates.
>>
>> Right now my question is related to constructors.  If I have a slot in
>> an S4 class that is itself an S4 object, is there a way to chain the
>> constructor so that I generate the internal object without first
>> creating an empty object.
>>
>> To be specific, I have an S4 class "reModule" that contains sparse
>> matrices of S4 class "dgCMatrix" and some information that is atomic.
>> The S4 definition is (more-or-less)
>>
>> setClass("reModule", representation(Lambda = "dgCMatrix", Zt =
>> "dgCMatrix", theta = "numeric", Lind = "integer"))
>>
>> and the definition of dgCMatrix is
>>
>> setClass("dgCMatrix", representation(Dim = "integer", i = "integer", p
>> = "integer", x = "numeric")
>>
>> Using Rcpp I define C++ classes
>>
>> class dgCMatrix {
>> public:
>>     dgCMatrix(Rcpp::S4);
>>
>>     Rcpp::IntegerVector Dim, i, p;
>>     Rcpp::NumericVector x;
>> };
>>
>> class reModule {
>> public:
>>     reModule(Rcpp::S4);
>>
>>     dgCMatrix Lambda, Zt;
>>     Rcpp::NumericVector theta;
>>     Rcpp::IntegerVector Lind;
>> };
>>
>> If I define a constructor for the reModule without chaining to
>> constructors for the dgCMatrix objects then I need to define a
>> dgCMatrix::dgCMatrix() constructor and then redefine the Lambda and Zt
>> members inside the reModule constructor.  I think a more idiomatic C++
>> constructor definition is to chain to the other constructor as in
>>
>> using namespace Rcpp;
>>
>> reModule::reModule(S4 xp) :
>>     Lambda(S4(xp.slot("Lambda"))),
>>     Zt(S4(xp.slot("Zt"))),
>>     ...
>> {
>> }
>>
>> but the compiler doesn't like constructing an S4 object from an
>> Rcpp::RObject::SlotProxy.
>
> This we can fix (I guess). I have not been using the "S4" class too much
> beyond hello world classes.
>
> The code generation idea sounds great. I'm curious to see this going. Would
> you generate a c++ class skeleton by marshalling the S4 class definition,
> would this include methods ? There might be scope for having this R to C++
> compiler in a separate package

For the time being I am thinking only of generating class definitions
for C++ and default constructors.  The problem with translating
methods from S4 to C++ is multiple dispatch in S4.  One of the big
advantages of S4 as a class system is multiple dispatch on methods,
which is possible because the methods exist outside the class
definition.  We use this extensively in the Matrix package in defining
methods for matrix multiplication and solutions of linear systems.
For both those situations the choice of the method should take into
account the classes of the first two arguments.  Consider the output
of

library(Matrix)
showMethods("%*%")
showMethods("solve")
showMethods("crossprod")
showMethods("tcrossprod")

Those would not translate readily to C++
>> The way I have gotten around this is to use
>>    Lambda(S4(SEXP(xp.slot("Lambda"))))
>> etc.
>>
>> Is that a reasonable construction to use?
>
> Yes, in that it gets the job done. but using the first construct should
> work.

I don't object to using that construction.  Because Rcpp is a
collection of templates I don't think this will add overhead in the
compiled code - it just adds a bit of work for the compiler.


More information about the Rcpp-devel mailing list