[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