Check if objects are of a specific type and cast them if not
cast_if_not.Rd
If any of the named expressions in ...
are not of the same type,
then the object attempts to be cast to the type specified in the expression.
Expressions are evaluated and variables are assigned into the environment
specified by the .env
argument. The checking of type and the type conversion
are from the vctrs package (using vctrs::vec_is
and vctrs::vec_cast) and thus stick to the vctrs type conversion rules.
Usage
cast_if_not(
...,
.lossy = FALSE,
.env = caller_env(),
.class = NULL,
.error_call = caller_env()
)
Arguments
- ...
any number of named R expressions, in the form of:
name_of_obj_to_cast = obj_of_type_to_cast_to
- .lossy
whether to allow lossy casting.
- .env
the environment to use for the evaluation of the casting expressions & the assignment of the casted variables. Cannot be the global environment.
- .class
class to assign to the error (passed to rlang::abort).
- .error_call
the call environment to use for the error (passed to rlang::abort).
Examples
# Will not alter the global environment so most examples here are wrapped with local().
x <- 1L
cast_if_not(x = integer()) |> try()
# => Error: Argument `call` cannot be the global environment.
local({
x <- 1L
cast_if_not(x = double())
class(x)
})
#> [1] "numeric"
local({
x <- 1.5
cast_if_not(x = integer()) |> try()
})
#> Error in eval(quote({ : Error in `cast_if_not()`
#> ℹ Can't convert from `x` <double> to <integer> due to loss of precision. •
#> Locations: 1
# => Error : Can't convert from `x` <double> to <integer> due to loss of precision.
local({
x <- 1.5
cast_if_not(x = integer(), .lossy = TRUE)
cat(x, class(x), sep = ", ")
})
#> 1, integer
# other objects can be used as the type to cast to, e.g.:
local({
x <- 1L
y <- 2.3
cast_if_not(x = y)
class(x)
})
#> [1] "numeric"
# cast_if_not works sequentially, so references to objects will be
# after they have been evaluated:
local({
x <- y <- 1L
cast_if_not(x = double(), y = x)
cat(class(x), class(y), sep = ", ")
})
#> numeric, numeric
myfunc <- \(x) {
cast_if_not(x = double())
class(x)
}
x <- 1L
myfunc(x) # x is cast to double within the function
#> [1] "numeric"
class(x) # x is still an integer outside the function
#> [1] "integer"
local({
x <- y <- z <- 1L
cast_if_not(x = double(), y = double(), z = double())
cat(class(x), class(y), class(z), sep = ", ")
})
#> numeric, numeric, numeric
# the `.env` argument determines the expression and assignment environment:
local({
x <- 1L
e <- new.env()
e$x <- 1L
cast_if_not(x = 1.5, .env = e)
cat(class(e$x), class(x), sep = ", ")
})
#> numeric, integer
# names (lhs) are checked to be in the `.env` environment,
# throwing an error if not found:
local({
x <- 1L
e <- new.env()
cast_if_not(x = 1.5, .env = e) |> try()
})
#> Error in eval(quote({ : Error in `cast_if_not()`
#> ℹ Objects `x` are not found in the `.env` environment specified.
# => Error: Objects `x` are not found in the `.env` environment specified.
# for expressions (rhs), the `.env` argument is preferentially chosen, but if not found
# then the normal R scoping rules apply:
local({
x <- 1.5
e <- new.env()
e$z <- 1L
cast_if_not(z = x, .env = e)
cat(class(e$z))
})
#> numeric