[Rcpp-devel] Rcpp modules and S3 dispatch on rbind/cbind

Dirk Eddelbuettel edd at debian.org
Wed Jan 14 16:12:11 CET 2015


On 14 January 2015 at 15:00, Louis Aslett wrote:
| Sorry hit send prematurely ....
| 
| Just for the list record I think I've figured this out.  It turns out
| that there is an S4 approach to this now, whereby one actually sets

Sweet, and well done. 

I had meant to reply and suggest something like that -- Modules, after all,
are "just" extensions of S4 and don;t add anything to R proper (as they can't
go there anyway).  But I do so little S4 that my usual approach is to hide my
head in the sand til Martin Morgan comes along and explains it :)

| appropriate methods for the rbind2 and cbind2 functions in the methods
| package and then call:
| 
| methods:::bind_activation(on = TRUE)
| 
| This then recursively calls rbind2 and cbind2 with pairs of arguments
| whenever the base rbind/cbind are called with S4 arguments matching
| the signature.  Of course, it means all the other functions such as
| nrow/ncol/rownames/... must be overridden too for the classes used, in
| order that the knitting together that the methods package does will
| work correctly.  See the rbind.R source file in the methods package
| for details.
| 
| Hope that helps if anyone encounters this in future,

I think you also just volunteered a little demo for the Rcpp Gallery :)

[ Only half joking.  We seem to have a buglet at the knitr / jekyll side of
things as this works via sourceCpp but not in the default Rcpp Gallery
setup. ]

Dirk

 
| Louis
| 
| 
| On 12 January 2015 at 13:44, Louis Aslett <aslett at stats.ox.ac.uk> wrote:
| > I've encountered a problem when trying to perform S3 method dispatch
| > for rbind() with an Rcpp module I've written.  Obviously Rcpp modules
| > are S4, but as per many Google-able discussions, rbind/cbind can't
| > support S4 method dispatch due to the first argument being a
| > dot-dot-dot one, so S3 on the first argument type is the best that can
| > be done.  I think this is good enough for my problem as my types can't
| > be mixed with base types so I've a fairly short list of possible first
| > argument types and can disentangle in my own code.
| >
| > I won't bog the list down with my real problem which is hundreds of
| > lines of code ... I've managed to narrow it down to the following
| > minimal working example which produces the same issue (description to
| > follow below).
| >
| > == Start content of test.cpp ==
| > #include <Rcpp.h>
| > using namespace Rcpp;
| >
| > class TestClass1 {
| >   public:
| >     TestClass1() {}
| >     void hello() const {
| >       Rcout << "Hello world!" << std::endl;
| >     }
| > };
| >
| > class TestClass2 {
| >   public:
| >     TestClass2() {}
| >     void hello() const {
| >       Rcout << "Hello world!" << std::endl;
| >     }
| > };
| >
| > RCPP_MODULE(test_mod) {
| >   class_<TestClass1>( "TestClass1" )
| >   .constructor()
| >   .method("hello", &TestClass1::hello)
| >   ;
| >
| >   class_<TestClass2>( "TestClass2" )
| >   .constructor()
| >   .method("hello", &TestClass2::hello)
| >   ;
| > }
| > == End content of test.cpp==
| >
| > == Start example R script ==
| > Rcpp::sourceCpp('test.cpp')
| >
| > # Define S3 method for the Rcpp class types
| > rbind.Rcpp_TestClass1 <- function(...) {
| >   args <- list(...)
| >   cat("Calling type 1 hello\n")
| >   args[[1]]$hello()
| > }
| > rbind.Rcpp_TestClass2 <- function(...) {
| >   args <- list(...)
| >   cat("Calling type 2 hello\n")
| >   args[[1]]$hello()
| > }
| >
| > a <- new(TestClass1)
| > b <- new(TestClass2)
| >
| > # OK, this goes to plan ... I can has an Rcpp module, many of same
| > # type or mix with R types
| > rbind(a)
| > rbind(a,a)
| > rbind(a,2,matrix(1:4,2))
| > rbind(b)
| > rbind(b,b)
| > rbind(b,2,matrix(1:4,2))
| >
| > # ... but I can't mix two Rcpp module types
| > rbind(a,b)
| > rbind(b,a)
| >
| > # Get rid of one of the S3 methods and it works to mix Rcpp module types
| > rm(rbind.Rcpp_TestClass2)
| > rbind(a,b)
| > == End example R script ==
| >
| > The output for the problem part is:
| >
| >> # ... but I can't mix two Rcpp module types
| >> rbind(a,b)
| > Error in rbind(a, b) : environments cannot be coerced to other types
| >> rbind(b,a)
| > Error in rbind(b, a) : environments cannot be coerced to other types
| >
| > All other lines in the script behave as expected.
| >
| > So in a nut shell the problem seems to be that one can't have first
| > argument S3 method dispatch defined for more than one Rcpp module type
| > at a time.  I am mystified why this should be?  Any insights greatly
| > appreciated!
| >
| > All the best,
| >
| > Louis
| >
| >
| > PS In case this arrives twice in error I resent from my subscribed address.
| _______________________________________________
| 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

-- 
http://dirk.eddelbuettel.com | @eddelbuettel | edd at debian.org


More information about the Rcpp-devel mailing list