| Title: | Function Argument Validation |
| Version: | 2.0.0 |
| Description: | Validate function arguments succinctly with informative error messages. |
| License: | MIT + file LICENSE |
| Encoding: | UTF-8 |
| Imports: | cli, lifecycle, methods, rlang (≥ 1.1.0), tidyselect, vctrs |
| Suggests: | testthat (≥ 3.0.0), withr |
| Config/testthat/edition: | 3 |
| URL: | https://lj-jenkins.github.io/favr/, https://github.com/LJ-Jenkins/favr |
| Depends: | R (≥ 4.1.0) |
| BugReports: | https://github.com/LJ-Jenkins/favr/issues |
| Config/roxygen2/version: | 8.0.0 |
| NeedsCompilation: | no |
| Packaged: | 2026-08-20 07:42:11 UTC; lukej |
| Author: | Luke Jenkins |
| Maintainer: | Luke Jenkins <luke-jenkins-dev@outlook.com> |
| Repository: | CRAN |
| Date/Publication: | 2026-08-20 14:10:28 UTC |
favr: Function Argument Validation
Description
Validate function arguments succinctly with informative error messages.
Author(s)
Maintainer: Luke Jenkins luke-jenkins-dev@outlook.com (ORCID) [copyright holder]
Authors:
Luke Jenkins luke-jenkins-dev@outlook.com (ORCID) [copyright holder]
See Also
Useful links:
Report bugs at https://github.com/LJ-Jenkins/favr/issues
Ensure the truth of R expressions
Description
These functions were deprecated in favour of check(), abortifnot()
and abortif().
If any of the expressions in ... are not all TRUE, abort
is called for the first expression which was not (all) TRUE. The names
of expressions can be used as the error message or a single default error
message can be given using .message. Both are passed to
format_inline for formatting.
Usage
abort_if_not(..., .message = NULL, .error_call = caller_env())
abort_if(..., .message = NULL, .error_call = caller_env())
Arguments
... |
any number of R expressions, which should each evaluate to
(a logical vector of all) |
.message |
single default error message for non-named expressions. |
.error_call |
the call environment to use for error messages (passed to abort). |
Details
abort_if is the opposite of abort_if_not,
i.e. expressions should evaluate to (all) FALSE for no error to
occur. See enforce and schema for a non data-masked
and data-masked version of abort_if_not with options for size
recycling and type casting.
Value
NULL, called for side effects only.
Examples
# 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().
abort_if_not(1 == 1, all.equal(pi, 3.14159265), 1 < 2) # all TRUE
m <- matrix(c(1, 3, 3, 1), 2, 2)
abort_if_not(m == t(m), diag(m) == rep(1, 2)) # all TRUE
abort_if_not(1) |> try()
# A custom error message can be given for each expression:
m[1, 2] <- 12
abort_if_not("{.var m} must be {.cls symmetric}" = m == t(m)) |>
try()
# Alternatively, one error message can be used for all
# expressions:
abort_if_not(
m[1, 1] == 1,
diag(m) == rep(2, 2),
.message = "{.var m} has a diagonal of: {diag(m)}"
) |> try()
# The `.error_call` argument can be used to specify where the
# error occurs, by default this is the caller environment:
myfunc <- function(x) abort_if_not(x)
myfunc(FALSE) |> try()
# abort_if() errors if any argument does not evaluate to
# (all) FALSE:
abort_if(1 == 1) |> try()
# Injection can be used:
x <- "my error"
abort_if_not({{ x }} := FALSE) |> try()
abort_if_not(!!x := FALSE) |> try()
abort_if_not(FALSE, .message = "{x}") |> try()
x <- list("my {.var bang-bang-bang} error" = FALSE)
abort_if_not(!!!x) |> try()
Ensure the truth of R expressions
Description
If any of the expressions in ... are not (all) TRUE,
cli_abort() is called, producing an error
message indicating the first expression which was not (all)
TRUE.
For abortif(), the opposite is true, i.e. expressions
should evaluate to (all) FALSE for no error to occur.
Usage
abortifnot(
...,
message = NULL,
call = .envir,
.envir = parent.frame(),
.frame = .envir,
abort_args = NULL
)
abortif(
...,
message = NULL,
call = .envir,
.envir = parent.frame(),
.frame = .envir,
abort_args = NULL
)
Arguments
... |
Any number of R expressions, which should each evaluate to
(a If an expression is named, the name will be used in the error message
instead of the default message or the |
message |
Default error message for non-named expressions. |
call |
An execution environment, defused function call, or |
.envir |
Environment to evaluate the cli formatting of the error
message in. Passed to |
.frame |
The throwing context. Passed to
|
abort_args |
A list of additional arguments to pass to
|
Value
NULL invisibly if the checks pass, otherwise an error is thrown.
See Also
stopifnot() for the base R function this is based on.
check() and check_with() for a non data-masked
and data-masked version of abortifnot() with tidy evaluation and
injection support.
Examples
abortifnot(1 == 1, all.equal(pi, 3.14159265), 1 < 2) # all TRUE
m <- matrix(c(1, 3, 3, 1), 2, 2)
abortifnot(m == t(m), diag(m) == rep(1, 2)) # all TRUE
abortifnot(1) |> try()
# A custom error message can be given for each expression:
m[1, 2] <- 12
abortifnot("{.var m} must be {.cls symmetric}" = m == t(m)) |>
try()
# Alternatively, one error message can be used for all
# expressions.
abortifnot(
m[1, 1] == 1,
diag(m) == rep(2, 2),
message = "{.var m} has a diagonal of: {diag(m)}"
) |> try()
# The `call` argument can be used to specify where the
# error occurs, by default this is the caller environment.
myfunc <- function(x) abortifnot(x)
myfunc(FALSE) |> try()
# abortif() errors if any argument does not evaluate to
# (all) FALSE.
abortif(c(T, F)) |> try()
abortif(c(T, NA)) |> try()
Bare type predicates
Description
These functions were deprecated as they offer little benefit over lapply().
Wrappers around rlang type predicates that allow multiple objects to be passed. The following documentation is adapted from the rlang documentation:
These predicates check for a given type but only return TRUE for
bare R objects. Bare objects have no class attributes. For example,
a data frame is a list, but not a bare list.
The predicates for vectors include the
.nargument for pattern-matching on the vector length.Like
are_atomic()and unlike base Ris.atomic()for R < 4.4.0,are_bare_atomic()does not returnTRUEforNULL. Starting in R 4.4.0,is.atomic(NULL)returns FALSE.Unlike base R
is.numeric(),are_bare_double()only returnsTRUEfor floating point numbers.
Usage
are_bare_list(..., .n = NULL, .all = FALSE)
are_bare_atomic(..., .n = NULL, .all = FALSE)
are_bare_vector(..., .n = NULL, .all = FALSE)
are_bare_integer(..., .n = NULL, .all = FALSE)
are_bare_double(..., .n = NULL, .all = FALSE)
are_bare_complex(..., .n = NULL, .all = FALSE)
are_bare_character(..., .n = NULL, .all = FALSE)
are_bare_string(..., .n = NULL, .all = FALSE)
are_bare_logical(..., .n = NULL, .all = FALSE)
are_bare_raw(..., .n = NULL, .all = FALSE)
are_bare_bytes(..., .n = NULL, .all = FALSE)
are_bare_numeric(..., .n = NULL, .all = FALSE)
Arguments
... |
Objects to be tested. |
.n |
Expected lengths of the vectors. |
.all |
Whether to return if all arguments are TRUE. |
Details
The optional input of .n can be given values
that map to the arguments in .... If a unnamed vector/list, the input must
either be the same length as the number of arguments given to ..., or
length 1: which is then recycled to the number number of arguments
given to .... Alternatively, a named vector/list can be given, where
the values for matching named elements are passed to the type predicate,
but unmatched names are passed NULL.
Value
Named logical, or unnamed boolean if .all is TRUE.
See Also
are-type-predicates, are-scalar-type-predicates
Examples
x <- 1
y <- list()
class(y) <- c("my_class", class(y))
z <- mean
are_bare_list(x, y, z, list(1))
# `.all` can be given to test if all inputs
# evaluate to TRUE
are_bare_list(x, y, z, list(1), .all = TRUE)
# scalar inputs to `.n` are recycled to number of inputs
are_bare_list(x, y, z, list(1), .n = 2)
# inputs to `.n` matching the number of inputs
# are applied sequentially
are_bare_list(list(), y, list(1, 2, 3), list(1), .n = c(0, 0, 3, 1))
# named inputs to `.n` are applied to the matching input
# names, with the other inputs being given NULL
x <- list()
are_bare_list(x, y, list(1, 2, 3), list(1), .n = c(x = 5, "list(1)" = 2))
Scalar type predicates
Description
These functions were deprecated as they offer little benefit over lapply().
Wrappers around rlang scalar type predicates that allow multiple objects to be passed. The following documentation is adapted from the rlang documentation:
These predicates check for a given type and whether the vector is "scalar", that is, of length 1.
In addition to the length check, are_string() and are_bool()
return FALSE if their input is missing. This is useful for
type-checking arguments, when your function expects a single string
or a single TRUE or FALSE.
Usage
are_scalar_list(..., .all = FALSE)
are_scalar_atomic(..., .all = FALSE)
are_scalar_vector(..., .all = FALSE)
are_scalar_integer(..., .all = FALSE)
are_scalar_double(..., .all = FALSE)
are_scalar_complex(..., .all = FALSE)
are_scalar_character(..., .all = FALSE)
are_string(..., .string = NULL, .all = FALSE)
are_scalar_logical(..., .all = FALSE)
are_bool(..., .all = FALSE)
are_scalar_raw(..., .all = FALSE)
are_scalar_bytes(..., .all = FALSE)
Arguments
... |
Objects to be tested. |
.all |
Whether to return if all arguments are TRUE. |
.string |
A string/character vector to compare to the inputs. |
Details
The optional input of .string can be given character vectors
that map to the arguments in .... If unnamed vector/list, the input must
either be the same length as the number of arguments given to ..., or
length 1: which is then recycled to the number number of arguments
given to .... Alternatively, a named vector/list can be given, where
the values for matching named elements are passed to the type predicate,
but unmatched names are passed NULL. List inputs can pass different
character vectors for each dot argument. When a character vector is given for
a single argument, TRUE is returned if at least one element is equal.
Value
Named logical, or unnamed boolean if .all is TRUE.
See Also
are-type-predicates, are-bare-type-predicates
Examples
x <- 1
y <- list()
z <- mean
are_scalar_list(x, y, z, list(1))
# `.all` can be given to test if all inputs
# evaluate to TRUE
are_list(x, y, z, list(1), .all = TRUE)
Type predicates
Description
These functions were deprecated as they offer little benefit over lapply().
Wrappers around rlang type predicates that allow multiple objects to be passed. The following documentation is adapted from the rlang documentation:
These type predicates aim to make type testing in R more
consistent. They are wrappers around base::typeof(), so operate
at a level beneath S3/S4 etc.
Compared to base R functions:
The predicates for vectors include the
.nargument for pattern-matching on the vector length.Unlike
is.atomic()in R < 4.4.0,are_atomic()does not returnTRUEforNULL. Starting in R 4.4.0is.atomic(NULL)returns FALSE.Unlike
is.vector(),are_vector()tests if an object is an atomic vector or a list.is.vectorchecks for the presence of attributes (other than name).
Usage
are_list(..., .n = NULL, .all = FALSE)
are_atomic(..., .n = NULL, .all = FALSE)
are_vector(..., .n = NULL, .all = FALSE)
are_integer(..., .n = NULL, .all = FALSE)
are_double(..., .n = NULL, .finite = NULL, .all = FALSE)
are_complex(..., .n = NULL, .finite = NULL, .all = FALSE)
are_character(..., .n = NULL, .all = FALSE)
are_logical(..., .n = NULL, .all = FALSE)
are_raw(..., .n = NULL, .all = FALSE)
are_bytes(..., .n = NULL, .all = FALSE)
are_null(..., .all = FALSE)
Arguments
... |
Objects to be tested. |
.n |
Expected lengths of the vectors. |
.all |
If |
.finite |
Whether all values of the vectors are finite. The
non-finite values are |
Details
The optional inputs of .n and .finite can be given inputs
that map to the arguments in .... If a unnamed vector/list, the input must
either be the same length as the number of arguments given to ..., or
length 1: which is then recycled to the number number of arguments
given to .... Alternatively, a named vector/list can be given, where
the values for matching named elements are passed to the type predicate,
but unmatched names are passed NULL.
Value
Named logical, or unnamed boolean if .all is TRUE.
See Also
are-bare-type-predicates are-scalar-type-predicates
Examples
x <- 1
y <- list()
z <- mean
are_list(x, y, z, list(1))
# `.all` can be given to test if all inputs
# evaluate to TRUE
are_list(x, y, z, list(1), .all = TRUE)
# scalar inputs to `.n` and `.finite` are
# recycled to number of inputs
are_list(x, y, z, list(1), .n = 1)
# inputs to `.n` and `.finite` matching the
# number of inputs are applied sequentially
are_list(x, y, z, list(1), .n = c(1, 0, 1, 2))
# named inputs to `.n` and `.finite` are applied
# to the matching input names, with the other inputs
# being given NULL
are_list(x, y, z, list(1), .n = c(y = 1, "list(1)" = 2))
Are objects empty vectors or NULL?
Description
These functions were deprecated as they offer little benefit over lapply().
Usage
are_empty(..., .all = FALSE)
Arguments
... |
Objects to be tested. |
.all |
Whether to return if all arguments are TRUE. |
Value
Named logical, or unnamed boolean if .all is TRUE.
See Also
Examples
x <- 1
y <- NULL
z <- list()
are_empty(x, y, z, NULL)
are_empty(x, y, z, NULL, .all = TRUE)
are_empty(list(NULL))
Are vectors integer-like?
Description
These functions were deprecated as they offer little benefit over lapply().
Wrappers around rlang type predicates that allow multiple objects to be passed. The following documentation is adapted from the rlang documentation:
These predicates check whether R considers a number vector to be
integer-like, according to its own tolerance check (which is in
fact delegated to the C library). This function is not adapted to
data analysis, see the help for base::is.integer() for examples
of how to check for whole numbers.
Things to consider when checking for integer-like doubles:
This check can be expensive because the whole double vector has to be traversed and checked.
Large double values may be integerish but may still not be coercible to integer. This is because integers in R only support values up to
2^31 - 1while numbers stored as double can be much larger.
Usage
are_integerish(..., .n = NULL, .finite = NULL, .all = FALSE)
are_scalar_integerish(..., .finite = NULL, .all = FALSE)
are_bare_integerish(..., .n = NULL, .finite = NULL, .all = FALSE)
Arguments
... |
Objects to be tested. |
.n |
Expected lengths of the vectors. |
.finite |
Whether all values of the vectors are finite. The
non-finite values are |
.all |
If |
Details
The optional inputs of .n and .finite can be given inputs
that map to the arguments in .... If a unnamed vector/list, the input must
either be the same length as the number of arguments given to ..., or
length 1: which is then recycled to the number number of arguments
given to .... Alternatively, a named vector/list can be given, where
the values for matching named elements are passed to the type predicate,
but unmatched names are passed NULL.
Value
Named logical, or unnamed boolean if .all is TRUE.
See Also
are_bare_numeric for testing whether an object is a base numeric type (a bare double or integer vector).
Examples
x <- 10L
y <- 10.0
z <- 10.000001
are_integerish(x, y, z, TRUE)
#' # `.all` can be given to test if all inputs
# evaluate to TRUE
are_integerish(x, y, z, TRUE, .all = TRUE)
# scalar inputs to `.n` and `.finite` are
# recycled to number of inputs
are_integerish(x, y, z, TRUE, .n = 2)
# inputs to `.n` and `.finite` matching the
# number of inputs are applied sequentially
are_integerish(x, y, z, TRUE, .n = c(1, 2, 1, 1))
# named inputs to `.n` and `.finite` are applied
# to the matching input names, with the other inputs
# being given NULL
are_integerish(x, y, z, TRUE, .n = c(y = 2, "TRUE" = 1))
Are objects named?
Description
These functions were deprecated as they offer little benefit over lapply().
Wrappers around rlang predicates that allow multiple objects to be passed. The following documentation is adapted from the rlang documentation:
-
are_named()is a scalar predicate that checks that objects in...have anamesattribute and that none of the names are missing or empty (NAor""). -
are_named2()is likeare_named()but always returnsTRUEfor empty vectors, even those that don't have anamesattribute. In other words, it tests for the property that each element of a vector is named.are_named2()composes well withnames2()whereasare_named()composes withnames(). -
have_names()is a vectorised variant.
Usage
are_named(..., .all = FALSE)
are_named2(..., .all = FALSE)
have_names(..., .all = FALSE)
Arguments
... |
Objects to be tested. |
.all |
Whether to return if all arguments are TRUE. |
Value
are_named() and are_named2() return a named logical,
or unnamed boolean if .all is TRUE. have_names() is vectorised
and returns a list of logical vectors whhere each is as long as the
input object. When .all is TRUE for have_names(), all logical
vectors are collapsed and a boolean is returned.
See Also
are-bare-type-predicates rlang::is_named
Examples
# are_named() is a scalar predicate about the whole vector of names:
x <- c(a = 1, b = 2)
are_named(x, c(a = 1, 2))
are_named(x, c(a = 1, 2), .all = TRUE)
# Unlike are_named2(), are_named() returns `FALSE` for empty vectors
# that don't have a `names` attribute.
are_named(list(), vector())
are_named2(list(), vector())
# have_names() is vectorised
y <- c(a = 1, 2)
have_names(x, y, c(a = 1, 2, 3))
have_names(x, y, c(a = 1, 2, 3), .all = TRUE)
# Empty and missing names are treated as invalid:
invalid <- setNames(letters[1:5], letters[1:5])
names(invalid)[1] <- ""
names(invalid)[3] <- NA
are_named(invalid)
have_names(invalid)
# A data frame normally has valid, unique names
# but a matrix usually doesn't because the names
# are stored in a different attribute.
mat <- matrix(1:4, 2)
colnames(mat) <- c("a", "b")
are_named(mtcars, mat)
have_names(mtcars, mat)
Are objects TRUE or FALSE?
Description
These functions were deprecated as they offer little benefit over lapply().
Test if any number of inputs are TRUE or FALSE. Inputs are passed to isTRUE or isFALSE.
Usage
are_true(..., .all = FALSE)
are_false(..., .all = FALSE)
Arguments
... |
Objects to be tested. |
.all |
Whether to return if all arguments are TRUE. |
Value
Named logical, or unnamed boolean if .all is TRUE.
See Also
Examples
x <- TRUE
y <- 1
z <- mean
are_true(x, y, z, TRUE, 0)
are_true(x, y, z, TRUE, 0, .all = TRUE)
are_false(x, y, z, TRUE, 0)
are_false(x, y, z, TRUE, 0, .all = TRUE)
Array type checks
Description
Check if inputs are expected types and throw an error if not.
Usage
check_array(
x,
n = NULL,
nrow = NULL,
ncol = NULL,
...,
finite = FALSE,
allow_null = FALSE,
arg = caller_arg(x),
call = caller_env()
)
check_matrix(
x,
n = NULL,
nrow = NULL,
ncol = NULL,
...,
finite = FALSE,
allow_null = FALSE,
arg = caller_arg(x),
call = caller_env()
)
check_table(
x,
n = NULL,
nrow = NULL,
ncol = NULL,
...,
finite = FALSE,
allow_null = FALSE,
arg = caller_arg(x),
call = caller_env()
)
Arguments
x |
An object to check. |
n, nrow, ncol |
The expected length, number of columns, or number of
rows of |
... |
Additional arguments passed to |
finite |
Whether |
allow_null |
Whether |
arg |
An argument name as a string. This argument will be mentioned in error messages as the input that is at the origin of a problem. |
call |
The execution environment of a currently
running function, e.g. |
Details
These functions can be used with the bare() modifier to check if an
object is a bare R object (i.e. has no class attribute), and the length
modifiers at_least(), at_most(), and in_range() to modify
the behaviour of the length checking n, nrow, and ncol arguments.
Note that the bare() modifier uses is.object() for check_array() and
check_matrix(), but uses the S3-style check for check_table(), which
checks if "table" is the first class in the class vector.
Value
NULL invisibly if the check passes, otherwise an error is thrown.
Note
These check functions are wrappers of their corresponding
base functions is.array(), is.matrix() and is.table().
See Also
Other checks:
forbidden-value-checks,
inheritance-checks,
oop-checks,
path-checks,
property-checks,
s3-type-checks,
scalar-type-checks,
scalar-value-checks,
type-checks,
walk-check
Examples
a <- array(1:12, dim = c(3, 4))
check_array(a)
check_array(1:12) |> try()
m <- matrix(1:12, nrow = 3)
check_matrix(m)
check_matrix(1:12) |> try()
t <- table(c("a", "b", "a"))
check_table(t)
check_table(1:12) |> try()
class(m) <- c("my_matrix", class(m))
check_matrix(bare(m)) |> try()
check_array(a, n = 10) |> try()
check_array(a, n = at_least(10))
check_matrix(m, ncol = at_most(3)) |> try()
check_matrix(m, nrow = in_range(1, 10))
Cast objects to a given type
Description
This function was deprecated as there is rarely a need to
use it over vctrs::vec_cast().
The names of the ... expressions, which should be variables within
the .env envrionment, are attempted to be casted to the type specified
in the expression:
e.g., name_of_object_to_cast = object_of_type_to_cast_to. Expressions
are evaluated in the environment specified and objects are assigned back
into that same environment. Lossy casting can be undertaken by wrapping the
expression in a call to lossy, e.g., x = lossy(integer()). The
type conversion is from the vctrs package
and thus sticks to the vctrs type conversion rules.
Usage
cast_if_not(..., .env = caller_env(), .error_call = caller_env())
Arguments
... |
any number of named R expressions. |
.env |
the environment to use for the evaluation of the casting expressions and the assignment of the casted objects. |
.error_call |
the call environment to use for error messages (passed to abort). |
Details
See abort_if_not for general validation, recycle_if_not for recycling, and enforce and schema for non data-masked and data-masked validations, recycling and casting.
Value
NULL, but objects named in ... will be changed in the
.env environment specified.
Examples
# 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
cast_if_not(x = double())
class(x) # numeric
# By default, lossy casting is not allowed:
x <- c(1, 1.5)
cast_if_not(x = integer()) |> try()
# lossy casting can be enabled using `lossy()` call:
cast_if_not(x = lossy(integer()))
class(x) # integer
# Other objects can be used as the type to cast to, e.g.:
x <- 1L
y <- 2.3
cast_if_not(x = y)
class(x) # numeric
# Changed objects are available immediately:
x <- y <- 1L
cast_if_not(x = double(), y = x)
cat(class(x), class(y), sep = ", ") # numeric, numeric
myfunc <- function(x) {
cast_if_not(x = double())
class(x)
}
x <- 1L
myfunc(x) # x is cast to double within the function
class(x) # x is still an integer outside the function
# The `.env` argument determines the expression and assignment
# environment:
x <- 1L
e <- new.env()
e$x <- 1L
cast_if_not(x = 1.5, .env = e)
cat(
"environment 'e'", class(e$x), "local environment", class(x),
sep = ", "
) # environment 'e', numeric, local environment, integer
# Named objects (lhs) are checked to be in the `.env` environment,
# throwing an error if not found:
x <- 1L
e <- new.env()
cast_if_not(x = 1.5, .env = e) |> try()
# For expressions (rhs), the `.env` argument is preferentially
# chosen, but if not found then the normal R scoping rules
# apply:
x <- 1.5
e <- new.env()
e$z <- 1L
cast_if_not(z = x, .env = e)
class(e$z) # numeric
# The `.error_call` argument can be used to specify where the
# error occurs, by default this is the caller environment:
myfunc <- function(x) cast_if_not(x = character())
myfunc(FALSE) |> try()
# Injection can be used:
y <- 1L
x <- "y"
cast_if_not(!!x := double()) |> try()
class(y) # numeric
y <- 1L
x <- list(y = double())
cast_if_not(!!!x)
class(y) # numeric
# Objects are reverted to their original values if an error
# occur:
x <- y <- 1L
cast_if_not(x = double(), y = character()) |> try()
class(x) # integer
Check the truth of tidy evaluated expressions
Description
If any of the expressions in ... are not (all) TRUE,
cli_abort() is called, producing an error
message indicating the first expression which was not (all)
TRUE.
check_with() is a data-masked version of check(),
evaluating the expression in the context of .data.
Usage
check(
...,
message = NULL,
call = .envir,
.envir = parent.frame(),
.frame = .envir,
abort_args = NULL
)
check_with(
.data,
...,
message = NULL,
call = .envir,
.envir = parent.frame(),
.frame = .envir,
abort_args = NULL
)
Arguments
... |
Any number of R expressions, which should each evaluate to
(a If an expression is named, the name will be used in the error message
instead of the default message or the |
message |
Default error message for non-named expressions. |
call |
An execution environment, defused function call, or |
.envir |
Environment to evaluate the cli formatting of the error
message in. Passed to For |
.frame |
The throwing context. Passed to
|
abort_args |
A list of additional arguments to pass to
|
.data |
A data frame, list, or environment to evaluate the expressions in as a data mask. |
Value
NULL, called for side effects only.
See Also
abortifnot() for a more performant version without tidy evaluation and
injection support.
Examples
check(1 == 1, all.equal(pi, 3.14159265), 1 < 2) # all TRUE
data <- data.frame(x = 1:5, y = 6:10)
check_with(data, x < y, is.numeric(x), length(y) < 10) # all TRUE
# A custom error message can be given for each
# expression, with cli formatting.
check(
"message {.arg 1}" = TRUE, "message {.arg 2}" = FALSE
) |> try()
# check_with() names are also are evaluated in
# the context of `.data` then `.envir`.
x <- "env 'x'"
y <- "env 'y'"
data <- list(x = "data 'x'")
check_with(data, "{x}" = is.numeric(x)) |>
try()
check_with(data, "{y}" = is.numeric(x)) |>
try()
# Pronouns are supported in check_with() error
# messages, but must be spaced according to cli
# rules (e.g., use `{ .env$x}` instead of `{.env$x}`).
check_with(data, "{ .env$x}" = is.numeric(x)) |>
try()
# Alternatively, one error message can be used for all
# expressions.
x <- 1:3
check(
x > 0, x < 3,
message = "{.arg x} has incorrect values: {.val {x}}."
) |> try()
data <- data.frame(x = c("a", "b", "c"))
check_with(data,
is.numeric(x),
message = "{.arg x} is not numeric: {.val {x}}."
) |>
try()
# The `call` argument can be used to specify where the
# error occurs, by default this is the caller environment.
myfunc <- function(x) check(x)
myfunc(FALSE) |> try()
myfunc_with <- function(x, ...) check_with(x, ...)
myfunc_with(list(x = 1), x < 0) |> try()
# check() and check_with() error if any argument does
# not evaluate to (all) FALSE.
check(c(T, F)) |> try()
check_with(list(x = c(T, NA)), x) |>
try()
Ensure the truth of R expressions and cast/recycle objects.
Description
If any of the expressions in ... are not all TRUE, abort
is called for the first which was not (all) TRUE. Alternatively,
rlang formulas can
be used to pass multiple objects to validation formulas/functions,
and/or attempt safe type casting and size recycling using the
cast, recycle and coerce functions. The rhs of
formulas can be given in a list to pass multiple functions/formulas/calls.
Expressions are evaluated in the environment specified and objects
are assigned back into that environment. Type casting and recycling
are undertaken using the vctrs package
and thus apply vctrs type and size rules.
Usage
enforce(..., .env = caller_env(), .error_call = caller_env())
Arguments
... |
any number of R expressions or formulas to be evaluated. Expressions must evaluate to logical whilst formulas can use c on the lhs and either functions or formulas that evaluate to logical, or one of the type/size functions: cast, recycle or coerce on the rhs. The rhs of a formula can also be a list of multiple functions/formulas/calls. If an expression is named, or if the list element on the rhs of a formula is named, the name is passed to format_inline and is used in the error message. |
.env |
the environment to use for the evaluation of the expressions and the assignment of the objects. |
.error_call |
the call environment to use for error messages (passed to abort). |
Details
See abort_if_not for only validations and schema for a data-masked version of this function.
Value
NULL, but objects casted/recycled in ... will be changed in
the .env environment specified.
Examples
# 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
favr casting and recycling helpers
Description
These functions signal to favr functions to undergo casting, lossy casting, and/or recycling. Each can only be used wihtin calls to specific favr functions and will error if used outside them. Specifically:
-
lossy(): used withincast_if_not()for lossy casting. -
recycle(): used withinenforce()andschema()for recycling. -
coerce(): used withinenforce()andschema()for casting and recycling.
Usage
lossy(x)
cast(x, lossy = FALSE)
recycle(x)
coerce(type = NULL, size = NULL, lossy = FALSE)
Arguments
x |
input to be lossily casted for |
lossy |
logical, |
type |
object of type to cast to for |
size |
scalar integerish value to recycle to. |
Details
These functions add attributes and/or a class to their inputs that signal transformations to occur within the favr caller.
Value
No return value, called for side effects only. Will error if called outside of a favr calling context (see Description and Examples).
Examples
try(cast(10)) # errors outside of favr calling context
x <- 1.5
cast_if_not(x = lossy(integer()))
class(x) # integer
enforce(x ~ list(cast(double()), recycle(5)))
class(x) # numeric
length(x) # 5
x <- 1.5
enforce(x ~ coerce(type = integer(), size = 5, lossy = TRUE))
class(x) # integer
length(x) # 5
Forbidden value checks
Description
Check if inputs contain forbidden values and error if so.
Usage
check_no_na(
x,
...,
allow_null = FALSE,
arg = caller_arg(x),
call = caller_env()
)
check_finite(
x,
...,
allow_null = FALSE,
arg = caller_arg(x),
call = caller_env()
)
check_unique(
x,
...,
allow_null = FALSE,
arg = caller_arg(x),
call = caller_env()
)
check_nzchar(
x,
...,
allow_all_ws = TRUE,
allow_null = FALSE,
arg = caller_arg(x),
call = caller_env()
)
Arguments
x |
An object to check. |
... |
Additional arguments passed to |
allow_null |
Whether |
arg |
An argument name as a string. This argument will be mentioned in error messages as the input that is at the origin of a problem. |
call |
The execution environment of a currently
running function, e.g. |
allow_all_ws |
Whether |
Details
NA checks are done with anyNA();
finite checks are done with any() and is.finite();
unique checks are done with anyDuplicated();
zero chr checks are done with any() and nzchar();
If allow_all_ws = FALSE then whitespace elements are identified using
grepl("\\s+", x).
Input types are not checked, they are passed 'as is' to the functions
that do the forbidden value checking. The only exception is for NULL
inputs, which error if allow_null = FALSE.
Value
NULL invisibly if the check passes, otherwise an error is thrown.
Note
NA_character_ is not considered zero chr nor all whitespace.
See Also
Other checks:
array-type-checks,
inheritance-checks,
oop-checks,
path-checks,
property-checks,
s3-type-checks,
scalar-type-checks,
scalar-value-checks,
type-checks,
walk-check
Examples
x <- c(1, 2, NA)
check_no_na(x) |> try()
x <- c(1, 2, Inf)
check_finite(x) |> try()
x <- c(1, 2, 3, 1)
check_unique(x) |> try()
x <- c("a", "b", "")
check_nzchar(x) |> try()
x <- c("a", "b", " ")
check_nzchar(x, allow_all_ws = FALSE) |> try()
Check class inheritance of an object
Description
Check that an object inherits from a specific class (or classes) and throw an error if not.
Usage
check_inherits(
x,
class,
match = c("any", "exact", "all"),
...,
arg = caller_arg(x),
call = caller_env()
)
check_class(x, class, ..., arg = caller_arg(x), call = caller_env())
Arguments
x |
An object to check. |
class |
Character vector of class names to check against. |
match |
The behaviour to use for inheritance checking. See Details. |
... |
Additional arguments passed to |
arg |
An argument name as a string. This argument will be mentioned in error messages as the input that is at the origin of a problem. |
call |
The execution environment of a currently
running function, e.g. |
Details
The match argument specifies how to check the inheritance:
-
"any": the class vector ofxmust have at least one element in common withclass. -
"exact": the class vector ofxmust be identical toclass. -
"all": the class vector ofxmust contain all elements ofclassin the supplied order.
check_class() is a utility wrapper around check_inherits()
with match = "exact".
Value
NULL invisibly if the check passes, otherwise an error is thrown.
Note
These check functions are wrappers of their corresponding rlang counterparts.
See Also
Other checks:
array-type-checks,
forbidden-value-checks,
oop-checks,
path-checks,
property-checks,
s3-type-checks,
scalar-type-checks,
scalar-value-checks,
type-checks,
walk-check
Examples
# Default behaviour is to check for any inheritance.
x <- structure(1, class = c("a", "b", "c"))
check_inherits(x, c("x", "b", "y"))
check_inherits(x, c("x", "y")) |> try()
# `match = "exact"` checks for exact match of the class vector.
x <- structure(1, class = c("a", "b", "c"))
check_inherits(x, c("a", "b", "c"), match = "exact")
check_inherits(x, c("a", "b")) |> try()
# check_class() is a utility wrapper with match = "exact".
check_class(x, c("a", "b", "c"))
check_class(x, c("a", "b")) |> try()
# `match = "all"` checks that inheritance is from all
# of the classes in the supplied order.
x <- structure(1, class = c("a", "b", "c", "d", "e"))
check_inherits(x, c("b", "d"), match = "all")
check_inherits(x, c("d", "b"), match = "all") |> try()
Modify the behaviour of type checking functions
Description
Modify the type-checking, or length-checking behaviour of favr type checking functions.
Usage
bare(x, arg = caller_arg(x))
at_least(n, arg = caller_arg(n))
at_most(n, arg = caller_arg(n))
in_range(
n_min,
n_max,
arg_min = caller_arg(n_min),
arg_max = caller_arg(n_max)
)
Arguments
x |
An object to modify the check behaviour for. |
arg, arg_min, arg_max |
An argument name as a string. This argument will be mentioned in error messages as the input that is at the origin of a problem. |
n, n_min, n_max |
Single numeric value that is castable to an integer. Must be zero or positive. |
Details
Use bare() to check if a given object is a bare R object
(no class attribute, see is.object()), throwing an error if it is not
and passing the object on to the check if it is.
For S3 type checks, bare() checks that the object has the expected S3
type as the first element of the class vector.
To modify the behaviour of length checking arguments n, nrow, and
ncol (example described for n):
-
at_least(n)means the object must be at least length (>=)n. -
at_most(n)means the object must be at most length (<=)n. -
in_range(n_min, n_max)means the object length must be within the range of (>=)n_minand (<=)n_max.
Value
A list of class favr_modifier with named elements obj, bare
and arg for bare(), and at_least and/or at_most for the length
modifiers.
See Also
type-checks, scalar-type-checks, s3-type-checks, property-checks and s3-check-builders for the functions that these modifiers can be used with.
Examples
bare(1)
at_least(1)
at_most(1)
in_range(1, 2)
at_least(1.5) |> try()
check_integer(bare(factor(1))) |> try()
check_integer(1:5, n = at_least(10)) |> try()
check_integer(1:5, n = at_most(3)) |> try()
check_integer(1:5, n = in_range(2, 4)) |> try()
x <- as.Date("2000-01-01")
class(x) <- c("my_date", class(x))
check_date(bare(x)) |> try()
Check if an object is of a specific object-oriented programming type
Description
Check that an object is an S3, S4, S7, or R6 object.
Usage
check_s3(x, ..., allow_null = FALSE, arg = caller_arg(x), call = caller_env())
check_s4(x, ..., allow_null = FALSE, arg = caller_arg(x), call = caller_env())
check_s7(x, ..., allow_null = FALSE, arg = caller_arg(x), call = caller_env())
check_r6(x, ..., allow_null = FALSE, arg = caller_arg(x), call = caller_env())
Arguments
x |
An object to check. |
... |
Additional arguments passed to |
allow_null |
Whether |
arg |
An argument name as a string. This argument will be mentioned in error messages as the input that is at the origin of a problem. |
call |
The execution environment of a currently
running function, e.g. |
Details
S3 checks are performed by checking if the object has a class
attribute with is.object() and is not an S4 object.
S4 checks are performed using isS4().
S7 and R6 checks are performed by checking for the inheritance of
the S7_object and R6 classes, respectively.
Value
NULL invisibly if the check passes, otherwise an error is thrown.
See Also
Other checks:
array-type-checks,
forbidden-value-checks,
inheritance-checks,
path-checks,
property-checks,
s3-type-checks,
scalar-type-checks,
scalar-value-checks,
type-checks,
walk-check
Examples
check_s3(factor("a"))
check_s3(1:3) |> try()
methods::setClass("Person",
slots = c(name = "character", age = "numeric")
)
x <- methods::new("Person", name = "John", age = 30)
check_s4(x)
check_s4(factor("a")) |> try()
# trivial examples of inheritance checks for S7 and R6 objects
x <- structure(list(), class = "S7_object")
check_s7(x)
check_s7(factor("a")) |> try()
x <- structure(list(), class = "R6")
check_r6(x)
check_r6(factor("a")) |> try()
File and directory existence checks
Description
Check if inputs are existing directories or files and throw an error if not.
Usage
check_dir(x, ..., arg = caller_arg(x), call = caller_env())
check_file(
x,
...,
ext = NULL,
case = TRUE,
x_arg = caller_arg(x),
ext_arg = caller_arg(ext),
call = caller_env()
)
check_ext(
x,
ext,
...,
case = TRUE,
x_arg = caller_arg(x),
ext_arg = caller_arg(ext),
call = caller_env()
)
Arguments
x |
A path to check. |
... |
Additional arguments passed to |
arg, x_arg, ext_arg |
An argument name as a string. This argument will be mentioned in error messages as the input that is at the origin of a problem. |
call |
The execution environment of a currently running function, e.g.
|
ext |
A character vector of file extensions to check for. |
case |
A logical value indicating if the extension check should
be case-sensitive. If |
Value
NULL invisibly if the check passes, otherwise an error is thrown.
Note
The checking of extensions is done simply using endsWith().
See Also
Other checks:
array-type-checks,
forbidden-value-checks,
inheritance-checks,
oop-checks,
property-checks,
s3-type-checks,
scalar-type-checks,
scalar-value-checks,
type-checks,
walk-check
Examples
x <- file.path(R.home(), "library", "stats")
check_dir(x)
check_file(x) |> try()
x <- file.path(x, "DESCRIPTION")
check_file(x)
check_dir(x) |> try()
check_file(x, ext = c(".csv", ".xlsx")) |> try()
Object property checks
Description
Check if inputs have certain properties and error if not.
Usage
check_length(
x,
n,
...,
allow_null = FALSE,
arg = caller_arg(x),
call = caller_env()
)
check_nrow(
x,
nrow,
...,
allow_null = FALSE,
arg = caller_arg(x),
call = caller_env()
)
check_ncol(
x,
ncol,
...,
allow_null = FALSE,
arg = caller_arg(x),
call = caller_env()
)
check_size(
x,
n,
...,
allow_null = FALSE,
arg = caller_arg(x),
call = caller_env()
)
check_non_empty(x, ..., arg = caller_arg(x), call = caller_env())
check_named(
x,
...,
unique = FALSE,
allow_empty = TRUE,
arg = caller_arg(x),
call = caller_env()
)
Arguments
x |
An object to check. |
n, nrow, ncol |
The expected length/size, number of columns, or number of
rows of |
... |
Additional arguments passed to |
allow_null |
Whether |
arg |
An argument name as a string. This argument will be mentioned in error messages as the input that is at the origin of a problem. |
call |
The execution environment of a currently
running function, e.g. |
unique |
Whether |
allow_empty |
Whether |
Details
check_size() uses vec_size() to determine the size
of x, as opposed to length() which is used by
check_length().
Input types are not checked, they are passed 'as is' to the functions
that do the property checking. The only exception is for NULL inputs,
which error if allow_null = FALSE.
check_length(), check_size(), check_nrow() and check_ncol() can
be used with the length modifiers at_least(), at_most(), and
in_range() to modify the behaviour of the length checking n, nrow,
or ncol arguments.
Value
NULL invisibly if the check passes, otherwise an error is thrown.
See Also
Other checks:
array-type-checks,
forbidden-value-checks,
inheritance-checks,
oop-checks,
path-checks,
s3-type-checks,
scalar-type-checks,
scalar-value-checks,
type-checks,
walk-check
Examples
x <- c(1, 2, NA)
check_length(x, 4) |> try()
check_size(x, 4) |> try()
# length modifiers can be used
check_length(x, at_most(2)) |> try()
x <- data.frame(x = 1)
check_nrow(x, 2) |> try()
check_ncol(x, in_range(2, 4)) |> try()
check_size(x, at_least(2)) |> try()
x <- numeric(0)
check_non_empty(x) |> try()
check_non_empty(NULL) |> try()
x <- c(1, 2, 3)
check_named(x) |> try()
names(x) <- c("a", "b", "a")
check_named(x, unique = TRUE) |> try()
names(x) <- c("a", "b", "")
check_named(x, allow_empty = FALSE) |> try()
check_length(NULL, 2, allow_null = TRUE)
Recycle objects to a given size
Description
This function was deprecated as there is rarely a need to
use it over vctrs::vec_recycle().
The names of the ... expressions, which should be variables within
the .env envrionment, are attempted to be recycled to the size specified
in the expression:
e.g., name_of_object_to_recycle = size_to_recycle_to. Expressions
are evaluated in the environment specified and objects are assigned back
into that same environment. The object recycling is from the
vctrs package and thus stick to the
vctrs recycling rules.
Usage
recycle_if_not(..., .env = caller_env(), .error_call = caller_env())
Arguments
... |
any number of named R expressions. |
.env |
the environment to use for the evaluation of the recycling expressions and the assignment of the recycled objects. |
.error_call |
the call environment to use for error messages (passed to abort). |
Details
See abort_if_not for general validation, recycle_if_not for recycling, and enforce and schema for non data-masked and data-masked validations, recycling and casting.
Value
NULL, but objects named in ... will be changed in the
.env environment specified.
Examples
# 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 <- 1
recycle_if_not(x = 5)
length(x) # 5
# recycle_if_not() follows `vctrs` recycling rules:
x <- c(1, 1)
recycle_if_not(x = 6) |> try()
# Beware when using other objects as the size argument, e.g.:
x <- 1L
y <- c(1, 1, 1)
recycle_if_not(x = y) |> try()
# When using other objects, call vctrs::vec_size() on them first:
recycle_if_not(x = vctrs::vec_size(y))
length(x) # 3
# Changed objects are available immediately:
x <- y <- 1
recycle_if_not(x = 3, y = vctrs::vec_size(x))
cat(length(x), length(y), sep = ", ") # 3, 3
myfunc <- function(x) {
recycle_if_not(x = 3)
length(x)
}
x <- 1L
myfunc(x) # x is recycled to length 3 within the function
length(x) # x is still scalar outside the function
# The `.env` argument determines the expression and assignment
# environment:
x <- 1
e <- new.env()
e$x <- 1
recycle_if_not(x = 3, .env = e)
cat(
"environment 'e'", length(e$x), "local environment", length(x),
sep = ", "
) # environment 'e', 3, local environment, 1
# Named objects (lhs) are checked to be in the `.env` environment,
# throwing an error if not found:
x <- 1
e <- new.env()
recycle_if_not(x = 3, .env = e) |> try()
# For expressions (rhs), the `.env` argument is preferentially
# chosen, but if not found then the normal R scoping rules
# apply:
x <- 3
e <- new.env()
e$z <- 1
recycle_if_not(z = x, .env = e)
length(e$z) # 3
# The `.error_call` argument can be used to specify where the
# error occurs, by default this is the caller environment:
myfunc <- function(x) recycle_if_not(x = -5)
myfunc(1) |> try()
#' # Injection can be used:
y <- 1L
x <- "y"
recycle_if_not(!!x := 5) |> try()
length(y) # 5
y <- 1L
x <- list(y = 5)
recycle_if_not(!!!x)
length(y) # 5
# Objects are reverted to their original values if an error
# occur:
x <- y <- 1L
recycle_if_not(x = 5, y = -5) |> try()
length(x) # 1
S3 check builders
Description
Check builders for S3 types. These functions can be used to create
custom S3 type checks in the style of favr.
Usage
s3_vec_check(
x,
n,
type,
type_msg = paste0("a {.cls ", type, "}"),
...,
allow_null = FALSE,
arg = caller_arg(x),
call = caller_env()
)
s3_df_check(
x,
nrow,
ncol,
type,
type_msg = paste0("a {.cls ", type, "}"),
...,
allow_null = FALSE,
arg = caller_arg(x),
call = caller_env()
)
Arguments
x |
An object to check. |
n, nrow, ncol |
The expected length, number of columns, or number of
rows of |
type |
The expected |
type_msg |
A message describing the expected |
... |
Additional arguments passed to |
allow_null |
Whether |
arg |
An argument name as a string. This argument will be mentioned in error messages as the input that is at the origin of a problem. |
call |
The execution environment of a currently
running function, e.g. |
Details
Inputs are passed to check_inherits() to check that x inherits from
the expected S3 type. This means that error messages about inheritance
will always show the expected S3 type in the cli format of
{.cls <expected_s3_type>}.
The type_msg argument is used to customise the error message when a
different check fails (e.g., length), where the grammar may require
different phrasing. For example, the default value is
"a {.cls <expected_s3_type>}", but many favr functions use
"a {.cls <expected_s3_type>} vector". Also consider where 'an' is
more appropriate than 'a'.
These functions can be used with the bare() modifier to check if
an object is a bare S3 object (where the expected S3 type is the first
class in the class attribute of x), and the length modifiers
at_least(), at_most(), and in_range() to modify the behaviour
of the length checking n, nrow, and ncol arguments.
Value
NULL invisibly if the check passes, otherwise an error is thrown.
Note
Although named _vec and _df, these functions could be used to check any
S3 type, not just vectors and data frames. Their names are intended to
indicate the expected behaviour of the check - for types that would
use either the length or dimension checking arguments.
Examples
# Create a custom type check for a hypothetical "my_class" S3 class
check_my_class <- function(
x,
n = NULL,
...,
allow_null = FALSE,
arg = caller_arg(x),
call = caller_env()
) {
s3_vec_check(
x,
n,
type = "my_class",
type_msg = "a {.cls my_class} vector",
...,
allow_null = allow_null,
arg = arg,
call = call
)
}
# inheritance errors use 'type'
check_my_class(1L) |> try()
x <- structure(1:3, class = "my_class")
check_my_class(x)
check_my_class(NULL, allow_null = TRUE)
# other errors use 'type_msg'
check_my_class(x, n = 2) |> try()
check_my_class(x, n = at_least(4)) |> try()
check_my_class(x, n = at_most(2)) |> try()
check_my_class(x, n = in_range(1, 2)) |> try()
class(x) <- c("another_class", class(x))
check_my_class(bare(x)) |> try()
S3 type checks
Description
Check if inputs are expected S3 types and throw an error if not.
Usage
check_date(
x,
n = NULL,
...,
allow_na = TRUE,
allow_null = FALSE,
arg = caller_arg(x),
call = caller_env()
)
check_posixct(
x,
n = NULL,
...,
allow_na = TRUE,
allow_null = FALSE,
arg = caller_arg(x),
call = caller_env()
)
check_posixlt(
x,
n = NULL,
...,
allow_na = TRUE,
allow_null = FALSE,
arg = caller_arg(x),
call = caller_env()
)
check_factor(
x,
n = NULL,
...,
finite = FALSE,
allow_null = FALSE,
arg = caller_arg(x),
call = caller_env()
)
check_ordered(
x,
n = NULL,
...,
finite = FALSE,
allow_null = FALSE,
arg = caller_arg(x),
call = caller_env()
)
check_vctr(
x,
n = NULL,
...,
allow_null = FALSE,
arg = caller_arg(x),
call = caller_env()
)
check_list_of(
x,
n = NULL,
...,
allow_null = FALSE,
arg = caller_arg(x),
call = caller_env()
)
check_data_frame(
x,
nrow = NULL,
ncol = NULL,
...,
allow_null = FALSE,
arg = caller_arg(x),
call = caller_env()
)
check_tibble(
x,
nrow = NULL,
ncol = NULL,
...,
allow_null = FALSE,
arg = caller_arg(x),
call = caller_env()
)
check_data_table(
x,
nrow = NULL,
ncol = NULL,
...,
allow_null = FALSE,
arg = caller_arg(x),
call = caller_env()
)
check_tidytable(
x,
nrow = NULL,
ncol = NULL,
...,
allow_null = FALSE,
arg = caller_arg(x),
call = caller_env()
)
Arguments
x |
An object to check. |
n, nrow, ncol |
The expected length, number of columns, or number of
rows of |
... |
Additional arguments passed to |
allow_na |
Whether |
allow_null |
Whether |
arg |
An argument name as a string. This argument will be mentioned in error messages as the input that is at the origin of a problem. |
call |
The execution environment of a currently
running function, e.g. |
finite |
Whether |
Details
These functions can be used with the bare() modifier to check if
an object is a bare S3 object (where the expected S3 type is the first
class in the class attribute of x), and the length modifiers
at_least(), at_most(), and in_range() to modify the behaviour
of the length checking n, nrow, and ncol arguments.
Value
NULL invisibly if the check passes, otherwise an error is thrown.
See Also
Other checks:
array-type-checks,
forbidden-value-checks,
inheritance-checks,
oop-checks,
path-checks,
property-checks,
scalar-type-checks,
scalar-value-checks,
type-checks,
walk-check
Examples
x <- as.Date("2000-01-01")
check_date(x)
check_date(1L) |> try()
class(x) <- c("my_date", class(x))
check_date(bare(x)) |> try()
x <- x + 1:5
check_date(x, n = 3) |> try()
check_date(x, n = at_least(10)) |> try()
check_date(x, n = at_most(3)) |> try()
check_date(x, n = in_range(6, 10)) |> try()
x <- data.frame(x = 1:3, y = 1:3)
check_tibble(x) |> try()
class(x) <- c("my_tbl", "tbl_df", class(x))
check_tibble(x)
check_tibble(bare(x)) |> try()
check_tibble(x, nrow = 2) |> try()
check_tibble(x, nrow = at_least(4)) |> try()
check_tibble(x, nrow = in_range(1, 2)) |> try()
check_tibble(x, ncol = 3) |> try()
check_tibble(x, ncol = at_most(1)) |> try()
check_tibble(x, ncol = in_range(3, 5)) |> try()
Scalar type checks
Description
Check if inputs are scalars of an expected type and throw an error if not.
Usage
check_scalar_list(
x,
...,
allow_null = FALSE,
arg = caller_arg(x),
call = caller_env()
)
check_scalar_atomic(
x,
...,
allow_na = TRUE,
allow_null = FALSE,
arg = caller_arg(x),
call = caller_env()
)
check_scalar_vector(
x,
...,
allow_null = FALSE,
arg = caller_arg(x),
call = caller_env()
)
check_scalar_integer(
x,
...,
allow_na = TRUE,
allow_null = FALSE,
arg = caller_arg(x),
call = caller_env()
)
check_scalar_integerish(
x,
...,
finite = FALSE,
allow_null = FALSE,
arg = caller_arg(x),
call = caller_env()
)
check_scalar_double(
x,
...,
finite = FALSE,
allow_null = FALSE,
arg = caller_arg(x),
call = caller_env()
)
check_scalar_complex(
x,
...,
finite = FALSE,
allow_null = FALSE,
arg = caller_arg(x),
call = caller_env()
)
check_scalar_character(
x,
...,
allow_na = TRUE,
allow_null = FALSE,
arg = caller_arg(x),
call = caller_env()
)
check_scalar_logical(
x,
...,
allow_na = TRUE,
allow_null = FALSE,
arg = caller_arg(x),
call = caller_env()
)
check_scalar_raw(
x,
...,
allow_null = FALSE,
arg = caller_arg(x),
call = caller_env()
)
check_scalar_bytes(
x,
...,
allow_null = FALSE,
arg = caller_arg(x),
call = caller_env()
)
check_scalar_numeric(
x,
...,
finite = FALSE,
allow_null = FALSE,
arg = caller_arg(x),
call = caller_env()
)
Arguments
x |
An object to check. |
... |
Additional arguments passed to |
allow_null |
Whether |
arg |
An argument name as a string. This argument will be mentioned in error messages as the input that is at the origin of a problem. |
call |
The execution environment of a currently
running function, e.g. |
allow_na |
Whether |
finite |
Whether |
Details
These functions can be used with the bare() modifier to check if an
object is a bare R object (i.e. has no class attribute).
Value
NULL invisibly if the check passes, otherwise an error is thrown.
Note
To handle empty strings ("") use check_string() instead of
check_scalar_character().
These check functions are wrappers of their corresponding
rlang functions. The exception
is check_scalar_numeric(), which uses is.numeric().
See Also
Other checks:
array-type-checks,
forbidden-value-checks,
inheritance-checks,
oop-checks,
path-checks,
property-checks,
s3-type-checks,
scalar-value-checks,
type-checks,
walk-check
Examples
x <- 1L
check_scalar_integer(x)
check_scalar_double(x) |> try()
check_scalar_list(list(list()))
check_scalar_list(list(1, 2)) |> try()
check_scalar_character(NA_character_, allow_na = FALSE) |> try()
check_scalar_double(Inf, finite = TRUE) |> try()
check_scalar_logical(NULL, allow_null = TRUE)
x <- 1.0
check_scalar_integerish(x)
Scalar value checks
Description
Check if inputs are expected scalar values and throw an error if not.
Usage
check_true(
x,
...,
allow_null = FALSE,
arg = caller_arg(x),
call = caller_env()
)
check_false(
x,
...,
allow_null = FALSE,
arg = caller_arg(x),
call = caller_env()
)
check_bool(
x,
...,
allow_null = FALSE,
arg = caller_arg(x),
call = caller_env()
)
check_string(
x,
...,
string = NULL,
allow_empty = TRUE,
allow_null = FALSE,
arg = caller_arg(x),
call = caller_env()
)
Arguments
x |
An object to check. |
... |
Additional arguments passed to |
allow_null |
Whether |
arg |
An argument name as a string. This argument will be mentioned in error messages as the input that is at the origin of a problem. |
call |
The execution environment of a currently
running function, e.g. |
string |
A character vector of allowed values for |
allow_empty |
Whether |
Value
NULL invisibly if the check passes, otherwise an error is thrown.
See Also
Other checks:
array-type-checks,
forbidden-value-checks,
inheritance-checks,
oop-checks,
path-checks,
property-checks,
s3-type-checks,
scalar-type-checks,
type-checks,
walk-check
Examples
x <- TRUE
check_true(x)
check_false(x) |> try()
check_bool(NA) |> try()
check_bool(NULL, allow_null = TRUE)
x <- "a"
check_string(x)
check_string(x, string = c("a", "b"))
check_string(x, string = c("b", "c")) |> try()
check_string("", allow_empty = FALSE) |> try()
Ensure the truth of data-masked R expressions and cast/recycle named elements.
Description
If any of the expressions in ..., evaluated within the data mask
'data' (see data masking), are not all TRUE, abort
is called for the first which was not (all) TRUE. Alternatively,
rlang formulas can
be used to take advantage of tidyselect
features and pass multiple named elements in data to validation
formulas/functions, and/or attempt safe type casting and size recycling
using the cast, recycle and coerce functions.
The rhs of formulas can be given in a list to pass multiple
functions/formulas/calls. The .names and .size arguments can also be used
to check for given names and size of the data.frame/list itself. Type
casting, size checking, and recycling are undertaken using the
vctrs package and thus apply
vctrs type and size rules.
Usage
schema(data, ...)
## S3 method for class 'list'
schema(
data,
...,
.names = NULL,
.size = NULL,
.error_call = caller_env(),
.darg = caller_arg(data)
)
## S3 method for class 'data.frame'
schema(
data,
...,
.names = NULL,
.size = NULL,
.error_call = caller_env(),
.darg = caller_arg(data)
)
enforce_schema(data, ...)
## S3 method for class 'with_schema'
enforce_schema(data, ..., .error_call = caller_env(), .darg = caller_arg(data))
add_to_schema(data, ...)
## S3 method for class 'with_schema'
add_to_schema(
data,
...,
.names = NULL,
.size = NULL,
.error_call = caller_env(),
.darg = caller_arg(data)
)
Arguments
data |
a data.frame or list to use as the data mask. |
... |
any number of R expressions or formulas to be evaluated using
|
.names |
character vector of names which must be present in the |
.size |
positive scalar integerish value for the size that the |
.error_call |
the call environment to use for error messages (passed to abort). |
.darg |
the argument name of |
Details
See abort_if_not for a non-data-masked validation tool and enforce for a non-data-masked version of this function.
Value
data is returned with attached class with_schema and
attribute schema containing the schema call to be enforced later.
Examples
# 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
Type checks
Description
Check if inputs are expected types and throw an error if not.
Usage
check_list(
x,
n = NULL,
...,
allow_null = FALSE,
arg = caller_arg(x),
call = caller_env()
)
check_atomic(
x,
n = NULL,
...,
allow_na = TRUE,
allow_null = FALSE,
arg = caller_arg(x),
call = caller_env()
)
check_vector(
x,
n = NULL,
...,
allow_null = FALSE,
arg = caller_arg(x),
call = caller_env()
)
check_integer(
x,
n = NULL,
...,
allow_na = TRUE,
allow_null = FALSE,
arg = caller_arg(x),
call = caller_env()
)
check_integerish(
x,
n = NULL,
...,
finite = FALSE,
allow_null = FALSE,
arg = caller_arg(x),
call = caller_env()
)
check_double(
x,
n = NULL,
...,
finite = FALSE,
allow_null = FALSE,
arg = caller_arg(x),
call = caller_env()
)
check_complex(
x,
n = NULL,
...,
finite = FALSE,
allow_null = FALSE,
arg = caller_arg(x),
call = caller_env()
)
check_character(
x,
n = NULL,
...,
allow_na = TRUE,
allow_null = FALSE,
arg = caller_arg(x),
call = caller_env()
)
check_logical(
x,
n = NULL,
...,
allow_na = TRUE,
allow_null = FALSE,
arg = caller_arg(x),
call = caller_env()
)
check_raw(
x,
n = NULL,
...,
allow_null = FALSE,
arg = caller_arg(x),
call = caller_env()
)
check_bytes(
x,
n = NULL,
...,
allow_null = FALSE,
arg = caller_arg(x),
call = caller_env()
)
check_null(x, ..., arg = caller_arg(x), call = caller_env())
check_numeric(
x,
n = NULL,
...,
finite = FALSE,
allow_null = FALSE,
arg = caller_arg(x),
call = caller_env()
)
Arguments
x |
An object to check. |
n |
The expected length of |
... |
Additional arguments passed to |
allow_null |
Whether |
arg |
An argument name as a string. This argument will be mentioned in error messages as the input that is at the origin of a problem. |
call |
The execution environment of a currently
running function, e.g. |
allow_na |
Whether |
finite |
Whether |
Details
These functions can be used with the bare() modifier to check if
an object is a bare R object (i.e. has no class attribute), and the
length modifiers at_least(), at_most(), and in_range() to
modify the behaviour of the length checking n argument.
Value
NULL invisibly if the check passes, otherwise an error is thrown.
Note
check_null() cannot use bare() since NULL cannot have a class
attribute.
These check functions are wrappers of their corresponding
rlang functions. The exception is
check_numeric(), which uses is.numeric().
See Also
Other checks:
array-type-checks,
forbidden-value-checks,
inheritance-checks,
oop-checks,
path-checks,
property-checks,
s3-type-checks,
scalar-type-checks,
scalar-value-checks,
walk-check
Examples
x <- c(1, 2, 3)
check_integer(x) |> try()
check_integerish(x)
check_scalar_double(x) |> try()
check_double(x, n = 2) |> try()
check_double(x, n = at_least(4)) |> try()
check_double(x, n = at_most(2)) |> try()
check_double(x, n = in_range(1, 2)) |> try()
check_integer(bare(factor(1))) |> try()
check_double(c(1L, NA), allow_na = FALSE) |> try()
check_double(c(1.5, NA), finite = TRUE) |> try()
check_double(NULL, allow_null = TRUE)
# NULL list elements are not considered NULL
check_list(list(NULL), allow_null = TRUE) |> try()
Apply a predicate check to each element of a vector
Description
Apply a predicate check function to each element of a vector and throw an error if any element fails the check.
Usage
walk_check(.x, .f, ..., call = caller_env())
Arguments
.x |
A list or atomic vector. |
.f |
A function or formula to apply to each element of |
... |
Additional arguments passed to |
call |
The execution environment of a currently running function,
e.g. |
Details
walk_check() is designed to work with predicate functions,
throwing an error indicating the element that fails the check.
If you wish to use a function for .f that itself errors,
pass contextual information to that function
directly (e.g., using a shorthand anonymous function),
as the error will be thrown from that function's context
and won't have direct access to information from the caller
such as ... and call.
Value
.x invisibly if all checks pass, otherwise
an error is thrown.
See Also
Other checks:
array-type-checks,
forbidden-value-checks,
inheritance-checks,
oop-checks,
path-checks,
property-checks,
s3-type-checks,
scalar-type-checks,
scalar-value-checks,
type-checks
Examples
x <- list(1, 2, "a")
walk_check(x, is.atomic)
walk_check(x, ~ length(.x) == 1L)
walk_check(x, is.numeric) |> try()
walk_check(x, \(el) nchar(el) == 1L)
# Named elements are shown in the error.
x <- list(a = 1, b = 2, c = "a")
walk_check(x, is.numeric) |> try()