-
Notifications
You must be signed in to change notification settings - Fork 42
Use explicit class in S4_register()
#214
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
18d7bf0
02a7b9d
cf55ffd
0034882
f089bfa
d22838d
e43a926
0bae16c
bf8bfb0
a24f0a8
ade4371
2883762
7af0a8b
ea8f87e
7032501
6491999
8934a65
757ef2f
f8557a8
1f0ddbb
b516f2a
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,17 +1,44 @@ | ||
| #' Register an R7 class with S4 | ||
| #' | ||
| #' If you want to use [method<-] to register an method for an S4 generic with | ||
| #' an R7 class, you need to call `S4_register()` once. | ||
| #' @description | ||
| #' If you want to use an R7 class with S4 (e.g. to use [method<-] to register an | ||
| #' method for an S4 generic with an R7 class) you need to call `S4_register()` | ||
| #' once. This generates a full S4 class specification that: | ||
| #' | ||
| #' * Matches class name and inheritance hierarchy. | ||
| #' * Uses [validate()] as the validity method. | ||
| #' * Defines formal S4 slots to match R7 properties. The slot types are | ||
| #' matched to the R7 property types, with the exception of R7 unions, | ||
| #' which are unchecked (due to the challenges of converting R7 unions to | ||
| #' S4 unions). | ||
| #' | ||
| #' If `class` extends another R7 class or has a property restricted to an | ||
| #' R7 class, you you must register those classes first. | ||
| #' | ||
| #' @param class An R7 class created with [new_class()]. | ||
| #' @param env Expert use only. Environment where S4 class will be registered. | ||
| #' @export | ||
| S4_register <- function(class, env = parent.frame()) { | ||
| if (!is_class(class)) { | ||
| msg <- sprintf("`class` must be an R7 class, not a %s", obj_desc(class)) | ||
| stop(msg) | ||
| } | ||
|
|
||
| name <- class@name | ||
| contains <- double_to_numeric(setdiff(class_dispatch(class), "ANY")[-1]) | ||
|
|
||
| # S4 classes inherit slots from parent but R7 classes flatten | ||
| props <- class@properties | ||
| if (is_class(class@parent) && class@parent@name != "R7_object") { | ||
| parent_props <- class@parent@properties | ||
| props <- props[setdiff(names(props), names(parent_props))] | ||
| } | ||
| slots <- lapply(props, function(x) R7_to_S4_class(x$class)) | ||
|
|
||
| methods::setOldClass(class_dispatch(class), where = topenv(env)) | ||
| methods::setClass(name, contains = contains, slots = slots, where = topenv(env)) | ||
| methods::setValidity(name, function(object) validate(object), where = topenv(env)) | ||
| methods::setOldClass(c(name, contains), S4Class = name, where = topenv(env)) | ||
| invisible() | ||
| } | ||
|
|
||
| is_S4_class <- function(x) inherits(x, "classRepresentation") | ||
|
|
@@ -51,6 +78,25 @@ S4_to_R7_class <- function(x, error_base = "") { | |
| } | ||
| } | ||
|
|
||
| R7_to_S4_class <- function(x) { | ||
| switch(class_type(x), | ||
| NULL = "NULL", | ||
| any = "ANY", | ||
| S4 = S4_class_name(x), | ||
| R7 = R7_class_name(x), | ||
| R7_base = double_to_numeric(x$class), | ||
| R7_S3 = x$class[[1]], | ||
| R7_union = "ANY", | ||
| stop("Unsupported") | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I guess you could have an R7 property of |
||
| ) | ||
| } | ||
|
|
||
| # S4 uniformly uses numeric to mean double | ||
| double_to_numeric <- function(x) { | ||
| x[x == "double"] <- "numeric" | ||
| x | ||
| } | ||
|
|
||
| S4_base_classes <- function() { | ||
| list( | ||
| NULL = NULL, | ||
|
|
@@ -106,7 +152,7 @@ S4_class_name <- function(x) { | |
| } | ||
| } | ||
|
|
||
| S4_remove_classes <- function(classes, where = globalenv()) { | ||
| S4_remove_classes <- function(classes, where = parent.frame()) { | ||
| for (class in classes) { | ||
| methods::removeClass(class, topenv(where)) | ||
| } | ||
|
|
||
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,33 @@ | ||
| --- | ||
| title: "Minutes 2022-04-18" | ||
| --- | ||
|
|
||
| ## Changes | ||
|
|
||
| - All base wrappers use common naming scheme, e.g. `class_integer`, `class_numeric`, `class_missing`. | ||
| Exported wrappers for key S3 classes: `class_factor`, `class_Date`, `class_POSIXct`, and `class_data.frame`. | ||
|
|
||
| - `convert()` allows you to convert an object into another class. | ||
| \ | ||
| `super()` replaces `next_method()`. | ||
|
|
||
| - Require explicit `S4_register()` in order to use register a method for R7 class on a S4 generic. | ||
|
|
||
| - Can now register methods for double-dispatch base Ops (currently only works if both classes are R7, or the first argument is R7 and the second doesn't have a method for the Ops generic). | ||
|
|
||
| ## Discussion | ||
|
|
||
| - Lightweight syntax for unions: <https://github.com/RConsortium/OOP-WG/issues/224> --- no strong feelings against. | ||
|
|
||
| - Next steps | ||
|
|
||
| - Should we aim for a CRAN release of R7? | ||
| Allow us to get more feedback before it moves into base R and if tidyverse is to use R7, will also need some way to access in older versions of R. | ||
|
|
||
| - Serialization: <https://github.com/RConsortium/OOP-WG/issues/225> | ||
|
|
||
| - Base R extension points: <https://github.com/RConsortium/OOP-WG/issues/222> | ||
|
|
||
| - Will look into creating a patch to implement minimal set of changes. | ||
|
|
||
| - Will need to tweak package to use if in R devel, otherwise register some shims to make it work in current R. |
Uh oh!
There was an error while loading. Please reload this page.