# 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().
li <- list(x = 1L, y = "hi", z = \(x) x > 1)
li <- li |>
schema(x == 1, is.character(y), is.function(z)) # all TRUE
# The schema call is attached to the returned object and
# can be re-evaluated using enforce_schema():
li <- enforce_schema(li) # no error
li2 <- li
li2$x <- 2L
enforce_schema(li2) |> try()
# Calling `schema()` again overwrites any existing schema.
# Alternatively use `add_to_schema()` to add arguments to
# an existing schema (.size overwrites, other args append):
li <- li |>
add_to_schema(is.numeric(x), .names = c("x", "y"), .size = 3)
# A custom error message can be given for each expression by
# naming it:
schema(li,
"{.var y} must be {.cls numeric}, check input" = is.numeric(y)
) |> try()
# Formulas can be used to take advantage of tidyselect features
# on the lhs, with functions/additional formulas required on
# the rhs:
schema(li,
"multiple columns: {.pkg tidyselect}" = c(x, y) ~ is.integer
) |> try()
# Formulas can also be used with `cast()`, `recycle()`, and
# `coerce()` on the rhs to safely cast or recycle named
# elements:
class(schema(li, x ~ cast(double()))$x) # x is now numeric
length(schema(li, x ~ recycle(5))$x) # x is now length 5
schema(
li,
y ~ coerce(type = factor(), size = 5)
)$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:
schema(
li,
"generic message" = c(x, y, z) ~ list(
Negate(is.null),
"{.var specific} message" = Negate(is.function)
)
) |> try()
# Changed elements are available immediately:
df <- data.frame(x = 1L, y = 1L)
lapply(schema(df, x ~ cast(double()), y ~ cast(x)), class)
# both now numeric
# `.names` and `.size` arguments can be used to check that given
# names are present and that the data has the desired size:
schema(li, .names = c("a", "x", "y", "b")) |> try()
schema(li, .size = 5) |> try()
# The `.error_call` argument can be used to specify where the
# error occurs, by default this is the caller environment:
myfunc <- function(x, ...) schema(x, ...)
myfunc(li, x > 4) |> try()
# rlang pronouns and injection can be used, but care must be
# taken when using `.env` and `enforce_schema()` as the
# caller environment may have changed:
msg <- "{.var injection} msg"
cols <- quote(c(x, y))
schema(li, !!msg := !!cols ~ is.integer) |> try()
x <- 1L
li <- schema(li, x == .env$x) # no error
x <- 2
enforce_schema(li) |>
try() # error as the environmental variable has changed
Run the code above in your browser using DataLab