# NB: Some of these examples are expected to produce an error. To
# prevent them from terminating a run with example() they are
# piped into a call to try().
x <- 1L
y <- "hi"
z <- \(x) x > 1
enforce(x == 1, is.character(y), is.function(z)) # all TRUE
enforce(x == 2) |> try()
# A custom error message can be given for each expression by
# naming it:
enforce(
"{.var y} must be {.cls numeric}, check input" = is.numeric(y)
) |> try()
# Formulas can be used to take pass multiple objects
# on the lhs, with functions/additional formulas required on
# the rhs:
enforce(
"multiple objects using: {.fn c}" = c(x, y) ~ is.integer
) |> try()
# Formulas can also be used with `cast()`, `recycle()`, and
# `coerce()` on the rhs to safely cast or recycle objects:
enforce(x ~ cast(double()))
class(x) # x is now numeric
enforce(x ~ recycle(5))
length(x) # x is now length 5
enforce(y ~ coerce(type = factor(), size = 5))
print(y) # y is now factor and length 5
# Multiple calls can be used with formulas by wrapping them
# in `list()`, with the names of list elements being
# preferentially chosen for error messaging and the error
# message also showing which formula/function/call caused the
# error:
enforce(
"generic message" = c(x, y, z) ~ list(
Negate(is.null),
"{.var specific} message" = Negate(is.function)
)
) |> try()
# Changed elements are available immediately:
x <- y <- 1L
enforce(x ~ cast(double()), y ~ cast(x))
cat(class(x), class(y)) # both now numeric
# The `.error_call` argument can be used to specify where the
# error occurs, by default this is the caller environment:
myfunc <- function(...) enforce(...)
myfunc(x > 4) |> try()
# rlang injection can be used:
msg <- "{.var injection} msg"
cols <- quote(c(x, y))
enforce(!!msg := !!cols ~ is.integer) |> try()
# Objects are reverted to their original values if an error
# occur:
x <- y <- 1L
enforce(
x ~ cast(double()), y ~ recycle(5), y ~ is.function
) |> try() # errors
class(x) # integer
length(y) # 1
Run the code above in your browser using DataLab