[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