add check() + friends as generics to offer S3 validation
I'm currently shoehorning checkmate into S3 validation, where for every class in my package, I write some check.myclass() method, that, well, validates my class.
Since S3 validation comes up in a bunch of contexts, I also add check()s friends test(), expect() and assert().
This works surprisingly well, and seems to make my use of S3 (which doesn't come with built-in type validation) much more robust.
I've turned to using check(someClass) and friends basically whenever I somewhere touch an S3 object.
Tapping into the testthat and checkmate infrastructure makes this really powerful.
Would you have any interest in adding this to checkmate?
I think this might be useful for other users as well. It just makes S3 validation a lot easier.
If check() and friends generics shipped with checkmate that might also make it easier to document the other arguments that checkmate ships with (say, info, label, var.name and friends).
Could be something as simple as:
#' @title Validate S3 classes.
#' @description Generic function for validating S3 classes.
#' @export
#' @param x S3 classed object
check <- function(x) {
UseMethod("check")
}
#' @rdname check
test <- function(x) {
UseMethod("test")
}
#' @rdname check
test.default <- function(x) {
res <- check(x)
return(makeTest(res = res))
}
#' @rdname check
expect <- function(x, info = NULL, label = vname(x)) {
UseMethod("expect")
}
#' @rdname check
expect.default <- function(x, info = NULL, label = vname(x)) {
res <- check(x)
return(makeExpectation(x = x, res = res, info = info, label = label))
}
#' @rdname check
assert <- function(x, add = NULL, var.name = vname(x)) {
UseMethod("assert")
}
#' @rdname check
assert.default <- function(x, add = NULL, var.name = vname(x)) {
res <- check(x)
return(makeAssertion(x = x, res = res, var.name = var.name, collection = add))
}
This way, with .defaults defined, users don't even have to build a assert.MyClass() etc. – they just build a check.MyClass() and all the rest is offered automatically, by defaulting to the assert.default() methods, with actual methods dispatch happening only inside check.MyClass().
Ps.: Or, perhaps, checkS3() etc. to avoid NAMESPACE conflicts.
Pps: updated above code to make dispatch more elegant