Attempt S4 dispatch for intersect() and union(), maybe#305
Attempt S4 dispatch for intersect() and union(), maybe#305MichaelChirico wants to merge 8 commits intomainfrom
Conversation
|
I have a different approach, which uses the regular S4 dispatch. I put it into a separate PR #307, to better compare the two. |
|
What are your own thoughts on this approach? I see the main advantages as (1) simpler to maintain and (2) doesn't require us to become more "S4" in our package design generally. |
|
I agree with the advantages to be closer to a S3 package. I understand this S4 inclusion as a helper for a certain amount of time for other S4 packages, to adjust their code to use a more R consistent bit64 package. Earlier the other packages had to manouver around the missing consistency of the bit64 package. But that changes now. And later the S4 handling could be removed once the depending packages have adjusted. And then we are again a plain S3 package. So in general, I would prefer this approach if there is no desire to become S4 anyways in the near future. |
What should the downstream do though, exactly? I don't see a way around: as long as we |
|
In my understanding, S4 packages based on bit64 have to handle the S4 methods for their own classes, e.g. the intersect in nanotime. They have to have in mind, that integer64 is S3 and cannot generate their S4 objects, because they could be too complex and the base package does not know of the intended logic. In #301 I tried to give an example, the way I work with S4. I usually strip it down to the base data type (here setMethod("intersect", c("myInt64", "myCpl"), function(x, y) {
# here to put the special intersect logic for nanotime and nanoival
myCpl(intersect(x, y@.Data))
}) |
|
I'm still not seeing how that resolves this issue: library(nanotime)
library(bit64)
intersect # bit64::intersect |
But this should always be the case, because bit64 overloads intersect. The overload function has to handle all cases and if one needs the former function, one has to use And you want to achieve, that the |
hcirellu
left a comment
There was a problem hiding this comment.
I'm sorry for the late reply and that the changes in the test are all single line changes. I hope that still makes sense.
| #' @rdname sets | ||
| union = function(x, y) { | ||
| if ((isS4(x) || isS4(y)) && isGeneric("union")) { | ||
| s4_intersect = selectMethod("union", list(x=class(x), y=class(y))) |
There was a problem hiding this comment.
| s4_intersect = selectMethod("union", list(x=class(x), y=class(y))) | |
| s4_union = selectMethod("union", list(x=class(x), y=class(y))) |
| union = function(x, y) { | ||
| if ((isS4(x) || isS4(y)) && isGeneric("union")) { | ||
| s4_intersect = selectMethod("union", list(x=class(x), y=class(y))) | ||
| return(s4_intersect(x, y)) |
There was a problem hiding this comment.
| return(s4_intersect(x, y)) | |
| return(s4_union(x, y)) |
| #' @rdname sets | ||
| setdiff = function(x, y) { | ||
| if ((isS4(x) || isS4(y)) && isGeneric("setdiff")) { | ||
| s4_intersect = selectMethod("setdiff", list(x=class(x), y=class(y))) |
There was a problem hiding this comment.
| s4_intersect = selectMethod("setdiff", list(x=class(x), y=class(y))) | |
| s4_setdiff = selectMethod("setdiff", list(x=class(x), y=class(y))) |
| setdiff = function(x, y) { | ||
| if ((isS4(x) || isS4(y)) && isGeneric("setdiff")) { | ||
| s4_intersect = selectMethod("setdiff", list(x=class(x), y=class(y))) | ||
| return(s4_intersect(x, y)) |
There was a problem hiding this comment.
| return(s4_intersect(x, y)) | |
| return(s4_setdiff(x, y)) |
|
|
||
| #' @export | ||
| #' @rdname sets | ||
| is.element = function(el, set) { |
There was a problem hiding this comment.
| is.element = function(el, set) { | |
| if ((isS4(el) || isS4(set)) && isGeneric("is.element")) { | |
| s4_is_element = selectMethod("is.element", list(el=class(el), set=class(set))) | |
| return(s4_is_element(el, set)) | |
| } |
| # of integer64 vectors, but there is no complex64 class, so it just | ||
| # shows up on the inheritance chain as 'complex' --> need to ensure | ||
| # S4 gets invoked when possible even if the inputs don't directly test | ||
| # as being is("integer64"). |
There was a problem hiding this comment.
| # as being is("integer64"). |
| # shows up on the inheritance chain as 'complex' --> need to ensure | ||
| # S4 gets invoked when possible even if the inputs don't directly test | ||
| # as being is("integer64"). | ||
| expect_identical(intersect(x, x), "Successfully routed to S4 method!") |
There was a problem hiding this comment.
| expect_identical(intersect(x, x), "Successfully routed to S4 method!") |
| # S4 gets invoked when possible even if the inputs don't directly test | ||
| # as being is("integer64"). | ||
| expect_identical(intersect(x, x), "Successfully routed to S4 method!") | ||
| expect_identical(union(x, x), "Successfully routed to S4 method!") |
There was a problem hiding this comment.
| expect_identical(union(x, x), "Successfully routed to S4 method!") |
| # as being is("integer64"). | ||
| expect_identical(intersect(x, x), "Successfully routed to S4 method!") | ||
| expect_identical(union(x, x), "Successfully routed to S4 method!") | ||
| expect_identical(setdiff(x, x), "Successfully routed to S4 method!") |
There was a problem hiding this comment.
| expect_identical(setdiff(x, x), "Successfully routed to S4 method!") |
| expect_identical(intersect(x, x), "Successfully routed to S4 method!") | ||
| expect_identical(union(x, x), "Successfully routed to S4 method!") | ||
| expect_identical(setdiff(x, x), "Successfully routed to S4 method!") | ||
| }) |
hcirellu
left a comment
There was a problem hiding this comment.
I'm sorry for the late reply and that the changes in the test are all single line changes. I hope that still makes sense.
Closes #301. The rough idea is something Gemini pulled out of its hat as a way to avoid incurring anything too crufty/any dependency on {nanotime}.
With this (and #306), {nanotime} suite finally passes with devel {bit64}.
LMK if this makes sense to you.