[Rcpp-devel] dispatch on ::

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


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

-- 
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