0

I am working on a custom R6Class which will be the main structure of my R package. But the problem is that this:

setMethod('+', signature("MyClass"), function(e1, e2)1)

or

setMethod('+', signature("R6"), function(e1, e2)1)

are not working because when I run

a = MyClass$new()
a + a

I get the following error Error in a + a : non-numeric argument to binary operator

The only way I got it working is like this

`+.MyClass` = function(e1, e2) { return (1) }

but this is not useful since when load the package from scratch (library(MyClass)) on an empty environment +.MyClass is not defined.

So, how can operators for R6 classes be overloaded the right way?

Just in case, the snippet:

MyClass = R6Class(
   "MyClass",
   public = list(
      initialize = function() {
      }
   ),
   private = list(
   )
)

setMethod('+', signature("MyClass"), function(e1, e2)1)
a = MyClass$new()
a+a
Leonardo Lanchas
  • 1,616
  • 1
  • 15
  • 37

1 Answers1

2

When you load the package, +.MyClass should absolutely be available, assuming you've exported the function.1

I can demonstrate this with a minimal example, for which I used devtools -- I can't recommend enough the use of devtools for package creation. First, I create a minimal package structure:

devtools::create("dummypack", rstudio = FALSE)

Then I add a single R file in the "dummypack/R/" folder, "MyClass.R":

#' @export
MyClass = R6::R6Class(
    "MyClass",
    public = list(
        initialize = function() {
        }
    ),
    private = list(
    )
)

#' @export
`+.MyClass` = function(e1, e2) { return (1) }

The #' @export tags here are critical;2 what you need for this function to be available is that it is exported in the "dummypack/NAMESPACE" file (see the Namespaces chapter of Hadley Wickham's R packages). You need your NAMESPACE file to look like

export(MyClass)
export(`+.MyClass`)

to make sure both the class and the overloaded + operator are exported. Alternatively you could have a NAMESPACE like

exportPattern("^[^\\.]")

to export everything that does not begin with a . (this is the NAMESPACE file initially generated by devtools::create()). So, if you are not using devtools (and Roxygen -- roxygen2), you need to edit the NAMESPACE file yourself to make sure your functions are exported.

Then I run

devtools::install("dummypack/")

and in a fresh R session I run:

library(dummypack)
a = MyClass$new()
a+a
# [1] 1

to show that you get the result you'd want.


1 I would have thought this question could be easily marked as a duplicate. This question was the closest I found, but seemed to be a little too Roxygen-specific.

2 Note that those tags only help with your NAMESPACE file if you are using Roxygen (which would work if you were using devtools::document()). Also, for the minimal example I show, the tags aren't technically necessary since the default NAMESPACE generated by devtools::create() just has the line exportPattern("^[^\\.]") as discussed above. However, in the typical case you want these tags and either way the important thing is what ends up in the NAMESPACE file -- you need explicit export() statements in NAMESPACE or a statement such as exportPattern("^[^\\.]").

duckmayr
  • 16,303
  • 3
  • 35
  • 53