R functions and packages are great for sharing code, but it’s hard to
predict how end-users will implement them. Users might pass inputs that
your function wasn’t designed to handle, leading to incorrect results or
errors. For example, if a function expects a numeric vector (e.g.,
c(1, 2, 3)
) but receives a character vector
(e.g.,c("1", "2", "3")
), it may return an error.
The chk
package provides a set of functions that check
user-provided arguments and deliver meaningful error messages to guide
users when something goes wrong. Including chk
’s specially
designed functions when developing your R package will help improve user
experience, prevent errors, and make your code more robust by ensuring
consistent behavior across different inputs. This enhances the
reliability and reusability of your code.
Additionally, it can help with performance optimization by ensuring that your functions receive inputs of the appropriate size, thereby avoiding time-consuming calculations.
chk
is an R package for developers to check
user-supplied function arguments.
It is designed to be simple, customizable and fast.
chk
FunctionsBased on the function prefixes, we can classify chk
functions into three categories:
chk_
Functionsvld_
Functionscheck_
Functionschk_
Functionschk_
functions check the properties of individual
objects. For example, chk_flag(x)
checks whether
x
is a flag, i.e., a non-missing logical vector of length
1.
chk_
functions are called for their side-effects, i.e.,
they throw an informative error if the object fails the check. Although
do return an invisible copy of the first argument so they can be used in
pipes.
library(chk)
y <- TRUE
chk_flag(y)
y <- NA
chk_flag(y)
#> Error:
#> ! `y` must be a flag (TRUE or FALSE).
The error messages, which follow the tidyverse style
guide, are designed to allow the user to quickly identify the
problem with the argument value(s) they are providing. The errors are rlang errors of
subclass 'chk_error'
.
vld_
FunctionsEach chk_
function has a matching vld_
function which returns a flag indicating whether the object passed the
check.
The vld_
functions allow developers to provide their own
error messages.
check_
FunctionsThe check_
functions are more complex then the
chk_
functions which make them slower but makes doing some
general tests easier.
The chk_
functions are designed to be used within
functions. Consequently, when constructing an error message they use the
name of the object that they received as this is expected to be the name
of the argument.
fun1 <- function(x) {
chk_whole_number(x)
# use x
}
fun1(1)
y <- 1.3
fun1(x = y)
#> Error in `fun1()`:
#> ! `x` must be a whole number (non-missing integer scalar or double equivalent).
If this is not the case, developers can provide a different name
using the x_name
argument.
IMPORTANT NOTE
As the chk_
(and vld_
) functions are not
expected to be directly exposed to users they don’t check any of their
arguments (other than the object of interest of course!) to ensure that
they are as fast as possible.
The chk_flag()
function illustrates the general
structure of a chk_
function.
chk_flag
#> function(x, x_name = NULL){
#> if(vld_flag(x)) return(invisible(x))
#> if(is.null(x_name)) x_name <- deparse_backtick_chk(substitute(x))
#> abort_chk(x_name, " must be a flag (TRUE or FALSE)")
#> }
#> <bytecode: 0x7fe802835670>
#> <environment: namespace:chk>
A chk_
function initially checks the object (using its
vld_
partner) and if the object passes the check
immediately returns an invisible copy of the object. If, and only if,
the object fails the check does the chk_
function construct
and then throw an informative error message.
The deparse_backtick_chk()
and abort_chk()
functions are exported to make it easy for programmers to develop their
own chk_
functions. The chk-lgl.R
script illustrates the general template to use when developing your own
chk_
functions.
abort_chk()
The abort_chk()
function converts multiple arguments to
a string using paste0(..., collapse = '')
and provides
number sensitive sprintf
-like types. By default it also
capitalizes the first character and adds a missing period.