Search code examples
roperator-overloadingr-s4unary-operator

Unary plus for S4 class in R


I am experimenting with S4 classes in R and I was trying to define a plus (+) operator for my objects, i.e. overload the plus operator. I managed to overload the binary +, but I cannot figure out how to overload the unary plus. Here is a minimal working (unary operator not working) example for what I am trying to achieve:

setClass("HWtest",
         representation(expr  = "character"),
         prototype = list(expr  = NA_character_)
)

H <- new("HWtest", expr="Hello")
W <- new("HWtest", expr="World")

setMethod("+", signature(e1="HWtest", e2="HWtest"),
          function(e1,e2){
            new("HWtest", 
                expr = paste(e1@expr," + ",e2@expr))
          }
)

Now I can use the + operator and it works smoothly:

H+W
An object of class "HWtest"
Slot "expr":
[1] "Hello  +  World"

Now the unary plus of course doesn't work, so that has to be overloaded

+H
Error in +H : invalid argument to unary operator

So I tried to overload it in the following way:

setMethod("+", signature(e="HWtest"),
          function(e){
            new("HWtest", 
                expr = paste("+ ",e@expr))
          }
)

But this generates the error:

Error in match.call(fun, fcall) : 
  argument 1 matches multiple formal arguments

Is it possible to overload the unary plus? If so, how would I do it for this minimal example?


Solution

  • Try adding this (in addition to your binary overload):

    setMethod("+", signature(e1 = "HWtest", e2 = "missing"),
              function(e1){
                new("HWtest", 
                    expr = paste("+ ", e1@expr))
              }
    )
    

    R> +H
    An object of class "HWtest"
    Slot "expr":
    [1] "+  Hello"
    
    R> H + W
    An object of class "HWtest"
    Slot "expr":
    [1] "Hello  +  World"
    

    Citing the help file ?groupGeneric,

    [...] when a unary operator is encountered the Ops method is called with one argument and e2 is missing.

    And as Frank points out, the ?setMethod help file contains some useful information regarding the use of missing as a method signature (emphasis added):

    Two additional special class names can appear: "ANY", meaning that this argument can have any class at all; and "missing", meaning that this argument must not appear in the call in order to match this signature.