Using methods::setOldClass
inside a module.
#302
-
Hi there, I'm wanting to create my own S3 vector classes for work, eliminating some hacky use of doubles and using dedicated classes/types with more meaning, and am trying to use vctrs to assist me. Specifically, I've followed and replicated this example but for my own class, and I'm trying to do it in a module rather than a package because non-cran packages aren't really an option in the company's setup. ## Define the ait_decimal class ##
# The ait_decimal class is based on a record style vector.
# Underneath it is a list of three equal-length vectors, one logical and two integers.
box::use(
methods[setOldClass],
rlang[are_na],
vctrs[
field,
new_rcrd,
vec_assert,
vec_cast,
vec_cast_common,
vec_recycle_common,
vec_size
],
zeallot[`%<-%`]
)
# 1. Constructor ---------------------------------------------------------------
#' Internal constructor to create the ait_decimal type
#'
#' Asserts that `s` is aof type `logical()`, and that `c`, and `q` are of type
#' `integer()`. Creates the object through use of `vctrs::new_rcrd()`.
#'
#' @keywords internal
new_decimal <- function(s = logical(), c = integer(), q = integer(), digits = 20L) {
# Assert that s, c, and q are of the correct type.
vec_assert(s, ptype = logical())
vec_assert(c, ptype = integer())
vec_assert(q, ptype = integer())
vec_assert(digits, ptype = integer(), size = 1L)
# Create the class
new_rcrd(list(s = s, c = c, q = q), digits = digits, class = "ait_decimal")
}
# 2. Helper Constructor --------------------------------------------------------
#' A class for arbitrary precision decimal floating point values and arithmetic
#'
#' User-facing function to create a ait_decimal vector.
#' @param s Logical vector indicating the signs.
#' @param c Integer vector representing the coefficients.
#' @param q Integer vector representing the quotients.
#' @export
#' @examples
#'
#' ait_decimal(TRUE, 87, -3)
ait_decimal <- function(s = logical(), c = integer(), q = integer(), digits = 20L) {
scq_check(s, c, q)
# Cast for compatible types
c(c, q) %<-% vec_cast_common(c, q, .to = integer())
s <- vec_cast(s, to = logical())
# Enforce recycling rules
c(s, c, q) %<-% vec_recycle_common(s, c, q)
# Create ait_decimal vector
new_decimal(s = s, c = c, q = q, digits = digits)
}
# 3. Formally declare S3 class -------------------------------------------------
setOldClass(c("ait_decimal", "vctrs_rcrd", "vctrs_vctr"))
# 4. Attribute access ----------------------------------------------------------
#' Access the `units` attribute of an `ait_decimal` object.
#'
#' @keywords internal
ait_dec_units <- function(x) attr(x, "units")
# 5. Class check ---------------------------------------------------------------
#' Test if an object is of class `ait_decimal`
#' @param x An object.
#'
#' @return `TRUE` if object is of class `ait_decimal` and `FALSE` if it is not.
#' @export
is_ait_decimal <- function(x) inherits(x, "ait_decimal")
# 6. Format method -------------------------------------------------------------
#' ait_decimal format method for object printing
#'
#' @keywords internal
#' @export
format.ait_decimal <- function(x, ...) {
s <- ifelse(field(x, "s"), "-", "")
c <- field(x, "c")
q <- field(x, "q")
out <- paste0(s, c, "e", q)
out[are_na(s) | are_na(c) | are_na(q)] <- NA
out
}
box::register_S3_method("format", "ait_decimal", format.ait_decimal)
# 7. Abbreviated name type -----------------------------------------------------
# Used in column labels in tibble and str()
#' Abbreviated name for tibble columns
#'
#' @keywords internal
#' @export
vec_ptype_abbr.ait_decimal <- function(x) { "ait_decimal" }
box::register_S3_method("vec_ptype_abbr", "ait_decimal", vec_ptype_abbr.ait_decimal)
However if I try to use this module using
By commenting out lines, I can say this is caused by the use of Many thanks, Sabrina. P.S: Thank you very much for box, it's really been a life saver at the company I work for, where for our own internal library code, making non-cran packages installable from bitbucket using devtools isn't a possibility for various reasons - box + git subtree really saved the day and banished so much copy-pasted and "sourced" code in projects! |
Beta Was this translation helpful? Give feedback.
Replies: 1 comment 1 reply
-
Unfortunately the issue here is that ‘box‘ does not — and probably cannot! — support S4. While this is technically a bug in ‘box’, it’s really a limitation in R’s S4 system, and therefore (probably) not something I can fix on my side. See #284 for a discussion of that. I’ve never used ‘vctrs’ but as far as I know it is based on S3, not S4. So would it maybe work to simply remove the |
Beta Was this translation helpful? Give feedback.
Unfortunately the issue here is that ‘box‘ does not — and probably cannot! — support S4. While this is technically a bug in ‘box’, it’s really a limitation in R’s S4 system, and therefore (probably) not something I can fix on my side. See #284 for a discussion of that.
I’ve never used ‘vctrs’ but as far as I know it is based on S3, not S4. So would it maybe work to simply remove the
setOldClass
call? After all, the only purpose of that function is to make an S3 class usable with S4 methods.