[Rcpp-devel] dispatch on ::

Romain Francois romain at r-enthusiasts.com
Fri Jul 9 14:58:50 CEST 2010


Le 09/07/10 12:14, Romain Francois a écrit :
>
> Hello,
>
> One of the development routes of Rcpp is the concept of modules. In
> short an Rcpp module is a collection of C++ functions and classes
> directly exposed to R. The longer version of the description can be
> found in the vignette [1].
>
> When we expose a C++ class through a module, i.e:
>
> class World {
> public:
> World() : msg("hello"){}
> void set(std::string msg_) { this->msg = msg_; }
> std::string greet() { return msg; }
>
> private:
> std::string msg;
> };
>
> RCPP_MODULE(yada){
> using namespace Rcpp ;
> class_<World>( "World" )
> .method( "greet", &World::greet )
> .method( "set", &World::set )
> ;
>
> }
>
>
>  > yada <- Module( "yada" )
>
> an S4 class is also created so that we can achieve R-level method dispatch:
>
>  > setMethod( "show", "World", function(object){
> writeLines( sprintf( "<World object> : %s " , object$greet() ) )
> } )
>
>  > w <- new( yada$World )
>  > w
> <World object> : hello
>
>
> Now, the name used for the S4 dispatch is simply "World", which might
> (as John Chambers said here earlier) cause problems. For example what
> happens if two modules decide to expose the same class, etc ...
>
> So I'd like to do some sort of name mangling of the class to lower the
> chances of clashes, so instead of just "World" the class name could use
> something that identifies the module (for example a character version of
> the pointer address.
>
>  > sprintf( "rcpp_module_%s_%s", Rcpp:::externalptr_address( yada ),
> "World" )
> [1] "rcpp_module_0x102f499b8_World"
>
> We could hide this in a function so that we can do :
>
>  > setMethod( "show", somefunction( yada, "World" ), ... )
>
> but I find this a little bit too verbose, and would prefer something
> like this:
>
>  > setMethod( "show", yada::World , ... )
>
> Unfortunately, it seems that if I define a method for :: it breaks the
> original use, because of non standard evaluation:
>
>  > setMethod( "::", "Module", function(pkg, name ){
> +
> + sprintf( "rcpp_module_%s_%s", Rcpp:::externalptr_address( pkg ),
> "World" )
> + }
> + )
> Une nouvelle fonction générique est créée pour "::" dans ".GlobalEnv"
> [1] "::"
>
>  > mod::World
> [1] "rcpp_module_0x102f499b8_World"
>  >
>  > stats::rnorm
> Erreur : objet 'stats' introuvable
> Erreur dans stats::rnorm :
> erreur lors de l'évaluation de l'argument 'pkg' lors de la sélection
> d'une méthode pour la fonction '::'
>
>
> Any idea to work around that ?
>
>
>
> Another way would be to use $ instead, so we would :
>
>  > setMethod( "show", yada$World , ... )
>
> but again this does not work because the signature in setMethod expects
> a character vector and yada$World is not (this is a C++Class object).
>
>
>  > signature( x = mod$World )
> Erreur dans signature(x = mod$World) :
> mauvaise classe spécifiée pour l'élément 1 (doit être une simple chaîne
> de caractères)
>
> Maybe one way to deal with that is to make C++Class extend the character
> class ...
>
>
> Ideas ?
>
>
> [1] :
> http://cran.r-project.org/web/packages/Rcpp/vignettes/Rcpp-modules.pdf

Hmmm. I finally settled for the second option.

So now the class name is obfuscated to avoid clashes and the objects of 
class C++Class inherit from character so that these works :

setMethod( "show", yada$World , ... )
setMethod( "show", signature( object = yada$World ), ... )

Romain

-- 
Romain Francois
Professional R Enthusiast
+33(0) 6 28 91 30 30
http://romainfrancois.blog.free.fr
|- http://bit.ly/aJHNLV : Rmetrics slides
|- http://bit.ly/98Uf7u : Rcpp 0.8.1
`- http://bit.ly/c6YnCi : graph gallery collage



More information about the Rcpp-devel mailing list