|
| 1 | +#' Use an environment as the base type of an S7 class |
| 2 | +#' |
| 3 | +#' @description |
| 4 | +#' \ifelse{html}{ |
| 5 | +#' {\figure{lifecycle-experimental.svg}{options: alt='\[Experimental\]'}}}{\strong{\[Experimental\] |
| 6 | +#' }} |
| 7 | +#' |
| 8 | +#' `class_environment` is the [base][base_classes] wrapper for environments. |
| 9 | +#' Unlike all other R objects, environments have reference semantics, i.e., they |
| 10 | +#' are modified in place. It's not clear what all the implications of this are |
| 11 | +#' for S7, so we are marking the use of `class_environment` as experimental. |
| 12 | +#' |
| 13 | +#' Its use is subject to the following caveats: |
| 14 | +#' |
| 15 | +#' * [S7_data()] and `S7_data<-()` error, because swapping the underlying data |
| 16 | +#' would destroy the existing attributes. |
| 17 | +#' |
| 18 | +#' * The default [convert()] method errors when upcasting to an environment |
| 19 | +#' because stripping the subclass's properties would mutate `from` in place. |
| 20 | +#' |
| 21 | +#' @export |
| 22 | +#' @examples |
| 23 | +#' Counter <- new_class("Counter", class_environment) |
| 24 | +#' counter <- Counter() |
| 25 | +#' counter$n <- 0L |
| 26 | +#' |
| 27 | +#' # Reference semantics: `copy` and `counter` are the same object, so |
| 28 | +#' # mutating one is visible through the other. |
| 29 | +#' copy <- counter |
| 30 | +#' copy$n <- 10L |
| 31 | +#' counter$n |
| 32 | +class_environment <- NULL |
| 33 | + |
| 34 | +check_not_environment <- function(object, fn) { |
| 35 | + if (!is.environment(object)) { |
| 36 | + return(invisible()) |
| 37 | + } |
| 38 | + |
| 39 | + msg <- paste_c( |
| 40 | + sprintf("Can't call `%s` on an environment.\n", fn), |
| 41 | + "See ?class_environment for details." |
| 42 | + ) |
| 43 | + stop(msg, call. = FALSE) |
| 44 | +} |
| 45 | + |
| 46 | +# Define onload to avoid dependencies between files |
| 47 | +on_load_define_environment <- function() { |
| 48 | + class_environment <<- new_base_class("environment") |
| 49 | +} |
0 commit comments