Skip to contents

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