RConsortium / S7

S7: a new OO system for R
https://rconsortium.github.io/S7
Other
387 stars 33 forks source link

`super()` needs to work with `Ops` #357

Closed DavisVaughan closed 9 months ago

DavisVaughan commented 12 months ago

Possibly missing a method for this, and maybe chooseOpsMethod

library(S7)

foo <- new_class("foo", class_integer)

method(`+`, list(foo, class_any)) <- function(e1, e2) {
  foo(`+`(super(e1, class_integer), e2))
}

foo(1L) + 1
#> Error in super(e1, class_integer) + e2: non-numeric argument to binary operator

# are we missing this?
Ops.S7_super <- function(e1, e2) {
  S7:::base_ops[[.Generic]](e1, e2)
}

foo(1L) + 1
#> Error: Can't find method for generic `+(e1, e2)`:
#> - e1: <foo>
#> - e2: <double>
hadley commented 12 months ago

Hmmm, in this case, I think you want this:

library(S7)
foo <- new_class("foo", class_integer)

method(`+`, list(foo, class_double)) <- function(e1, e2) {
  foo(S7_data(e1) + as.integer(e2))
}

foo(1L) + 1
#> <foo> int 2

Created on 2023-09-15 with reprex v2.0.2

But we still need super in more complicated cases:

library(S7)
foo <- new_class("foo", class_integer)
foo2 <- new_class("foo2", foo)

method(`+`, list(foo, class_double)) <- function(e1, e2) {
  foo(S7_data(e1) + as.integer(e2))
}
method(`+`, list(foo2, class_double)) <- function(e1, e2) {
  foo2(super(e1, foo) + e2)
}

foo2(1L) + 1
#> Error in super(e1, foo) + e2: non-numeric argument to binary operator

Created on 2023-09-15 with reprex v2.0.2

mmaechler commented 12 months ago

Why do we need the 2nd

method(`+`, list(foo2, class_double)) <- function(.....) {....}

as foo2 is a foo and there is a (foo, class_double) method already?

hadley commented 12 months ago

@mmaechler it doesn't do anything here, except to illustrate why you might need super().