I am creating an S3 class in R for which I would like to be able to do comparisons like "<"
, ">"
, and "=="
. Rather than implement each of these separately from what I've read about group generics I believe I can do so using Ops()
but I haven't found any good examples of how to do this.
Suffice it to say that for myClass
I can create an as.integer.myClass()
function, and that to compare a
and b
I could just convert to integer first:
if(as.integer(a) < as.integer(b)) foo
This totally works, but I would so much rather write
if(a < b) foo
I thought this would work, but it doesn't:
Ops.myClass <- function(e1, e2) {
Ops(as.integer(e1), as.integer(e2))
}
a < b
Error in (function (classes, fdef, mtable) :
unable to find an inherited method for function ‘Ops’ for signature ‘"integer", "integer"’
Any help?
Thanks!
Note that Ops(my, my)
fails with the same error -- you're not invoking Ops
, but a generic that is a member of the Ops group. So get the generic and invoke it on the transformed types
Ops.my = function(e1, e2) get(.Generic)(as.integer(e1), as.integer(e2))
with
> my1 = structure(1:5, class="my")
> my2 = structure(5:1, class="my")
> my1 > my2
[1] FALSE FALSE FALSE TRUE TRUE
> my1 == my2
[1] FALSE FALSE TRUE FALSE FALSE
The general approach I have for this is to use .Generic
and switch on the method.
Ops.myClass <- function(e1, e2)
{
op = .Generic[[1]]
switch(op,
`<` = {
print("called less than function")
as.integer(e1) < as.integer(e2)
},
`>` = {
print("called greater than function")
as.integer(e1) > as.integer(e2)
},
stop("undefined operation")
)
}
a <- 1
b <- 3
class(a) <- "myClass"
class(b) <- "myClass"
a > b
[1] "called greater than function"
[1] FALSE
a < b
[1] "called less than function"
[1] TRUE