Dispatch of `rbind` and `cbind` for a `data.frame` Dispatch of `rbind` and `cbind` for a `data.frame` r r

Dispatch of `rbind` and `cbind` for a `data.frame`


As you mention yourself, using S4 would be one good solution that works nicely. I have not investigated recently, with data frames as I am much more interested in other generalized matrices, in both of my long time CRAN packages 'Matrix' (="recommended", i.e. part of every R distribution) and in 'Rmpfr'.

Actually even two different ways:
1) Rmpfr uses the new way to define methods for the '...' in rbind()/cbind(). this is well documented in ?dotsMethods (mnemonic: '...' = dots) and implemented in Rmpfr/R/array.R line 511 ff (e.g. https://r-forge.r-project.org/scm/viewvc.php/pkg/R/array.R?view=annotate&root=rmpfr)

2) Matrix uses the older approach by defining (S4) methods for rbind2() and cbind2(): If you read ?rbind it does mention that and when rbind2/cbind2 are used. The idea there: "2" means you define S4 methods with a signature for two ("2") matrix-like objects and rbind/cbind uses them for two of its potentially many arguments recursively.


The dotsMethod approach was suggested by Martin Maechler and implemented in the Rmpfr package. We need to define a new generic, class and a method using S4.

setGeneric("rbind", signature = "...")mychar <- setClass("myclass", slots = c(x = "character"))b <- mychar(x = "b")rbind.myclass <- function(...) "hello from rbind.myclass"setMethod("rbind", "myclass",      function(..., deparse.level = 1) {        args <- list(...)        if(all(vapply(args, is.atomic, NA)))          return( base::cbind(..., deparse.level = deparse.level) )        else          return( rbind.myclass(..., deparse.level = deparse.level))      })# these work as expectedrbind(b, "d")rbind(b, b)rbind(b, matrix())# this fails in R 3.4.3rbind(b, data.frame())Error in rbind2(..1, r) :    no method for coercing this S4 class to a vector

I haven't been able to resolve the error. See R: Shouldn't generic methods work internally within a package without it being attached?for a related problem.

As this approach overrides rbind(), we get the warning The following objects are masked from 'package:base': rbind.


I don't think you're going to be able to come up with something completely satisfying. The best you can do is export rbind.myclass so that users can call it directly without doing mypackage:::rbind.myclass. You can call it something else if you want (dplyr calls its version bind_rows), but if you choose to do so, I'd use a name that evokes rbind, like rbind_myclass.

Even if you can get r-core to agree to change the dispatch behavior, so that rbind dispatches on its first argument, there are still going to be cases when users will want to rbind multiple objects together with a myclass object somewhere other than the first. How else can users dispatch to rbind.myclass(df, df, myclass)?

The data.table solution seems dangerous; I would not be surprised if the CRAN maintainers put in a check and disallow this at some point.