Reputation: 7063
Assume you have an input a
which goes into an existing function fun
. I am looking for a function preserved(a, fun(a))
, which returns TRUE
, if the type is unchanged, FALSE
otherwise.
Example:
a <- 1L # [1] 1 - integer
b <- a[FALSE] # integer(0)
c <- a[2] # [1] NA
d <- ncol(a) # NULL
e <- a/0 # [1] Inf
f <- 1 # [1] 1 - numeric
g <- as.factor(a) # [1] 1 Levels: 1
Expected output:
preserved(a, 2L) = TRUE
preserved(a, b) = FALSE
preserved(a, c) = FALSE
preserved(a, d) = FALSE
preserved(a, e) = FALSE
preserved(a, f) = FALSE
preserved(a, f) = FALSE
preserved(a, g) = FALSE
A bad hack (not vectorized) would be
preserved <- function(a, b) {
if (length(b) == length(a)) {
if (is.na(b) == is.na(a) &
class(b) == class(a) &
is.null(b) == is.null(a) &
is.nan(b) == is.nan(a) &
is.factor(b) == is.factor(a)) {
return(TRUE)
} else {
return(FALSE)
}
} else {
return(FALSE)
}
}
Upvotes: 3
Views: 76
Reputation: 44585
If you just want to compare two objects, you probably want to use all.equal()
or identical()
rather than trying to generate every possible pairwise combination of classes (since that number could be infinite).
Something close to what you want that might be more useful is applying makeActiveBinding()
to issue messages (or warnings or errors) if type coercion is attempted:
# active binding
preserved <- local( {
x <- NULL
function(v) {
if (!missing(v)) {
if (class(x) != class(v)) {
message(sprintf("Object is being coerced from %s to %s", class(x), class(v)))
}
x <<- v
}
x
}
})
makeActiveBinding("z", preserved, .GlobalEnv)
z
## NULL
z <- 2
## Object is being coerced from NULL to numeric
z <- "hello"
## Object is being coerced from numeric to character
z <- factor("a", levels = c("a", "b", "c"))
## Object is being coerced from character to factor
z
## [1] a
## Levels: a b c
Upvotes: 2