Repository navigation
Expand file tree
/
Copy pathREADME.Rmd
More file actions
163 lines (133 loc) · 6.43 KB
/
Copy pathREADME.Rmd
File metadata and controls
163 lines (133 loc) · 6.43 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
---
output: github_document
---
```{r options, include = FALSE}
knitr::opts_chunk$set(
collapse = TRUE,
comment = "#>"
)
```
# checkinput
<!-- badges: start -->

[](https://github.com/JesseAlderliesten/checkinput/actions/workflows/check-standard.yaml)
[](https://github.com/JesseAlderliesten/checkinput/actions/workflows/check-no-suggests.yaml)
<!-- badges: end -->
With **checkinput**, you can write concise, flexible checks for input to
[R](https://www.r-project.org/) functions.
## Installation
Visit the [**checkinput** website](https://jessealderliesten.github.io/checkinput/)
to explore the package, or install **checkinput**
[from GitHub](https://github.com/JesseAlderliesten/checkinput)
using the following R code:
```{r installation, eval = FALSE}
if(!requireNamespace("remotes")) {
install.packages(pkgs = "remotes")
}
remotes::install_github(repo = "JesseAlderliesten/checkinput",
upgrade = FALSE, build_vignettes = TRUE, lib = NULL)
```
For more information about installing and configuring R, see my package
[**checkrpkgs**](https://jessealderliesten.github.io/checkrpkgs/).
## Example
Say you want to collect information on people's hobbies through an R function
in which it is optional for them to provide their name. With **checkinput**, you
could write a function like `list_hobbies()`:
```{r list_hobbies}
list_hobbies <- function(name, age, hobbies) {
stopifnot(is_character(name, allow_empty = TRUE, allow_NA = TRUE),
is_nonnegative(age), all_characters(hobbies))
list(name = name, age = age, hobbies = hobbies)
}
```
The checks inside `stopifnot()` ensure that `name` contains a single character
string that might be empty (`""`) or `NA`; `age` contains a single non-negative
number; `hobbies` contains at least one character string and does not contain
empty strings or `NA`s.
The base R equivalent of `list_hobbies()` would require much more code to check
the input, increasing the chance of coding errors and making it more difficult
to read:
```{r list_hobbies_base}
list_hobbies_base <- function(name, age, hobbies) {
stopifnot(is.character(name), is.atomic(name), is.null(dim(name)),
length(name) == 1L,
is.numeric(age), is.atomic(age), is.null(dim(age)),
length(age) == 1L, !is.na(age), age >= 0L,
is.character(hobbies), is.atomic(hobbies), is.null(dim(hobbies)),
length(hobbies) > 0L, all(nzchar(hobbies, keepNA = FALSE)),
!anyNA(hobbies))
list(name = name, age = age, hobbies = hobbies)
}
```
If the input passes all checks, both functions produce the same output:
```{r example}
library(checkinput)
hobbies_John <- c("books", "construction sets")
John_checkinput <- list_hobbies(name = "John", age = 25, hobbies = hobbies_John)
John_base <- list_hobbies_base(name = "John", age = 25, hobbies = hobbies_John)
identical(John_checkinput, John_base)
hobbies_baby <- "drinking milk"
baby_checkinput <- list_hobbies(name = "", age = 0, hobbies = hobbies_baby)
baby_base <- list_hobbies_base(name = "", age = 0, hobbies = hobbies_baby)
identical(baby_checkinput, baby_base)
```
When a check fails, error messages indicate the offending arguments:
```{r example2}
library(checkinput)
try(list_hobbies(name = "John", age = 25, hobbies = c(hobbies_John, "")))
try(list_hobbies(name = "", age = -1, hobbies = hobbies_baby))
```
## Design choices
The check functions of **checkinput** return either `TRUE` or `FALSE` and do
**not** throw errors for any input to `x`. Errors **are** thrown about invalid
input to arguments other than `x`, e.g., when values other than `TRUE` or
`FALSE` are used for argument `allow_NA`. This is explained in the
[vignette about design choices](https://jessealderliesten.github.io/checkinput/articles/design_choices.html):
`vignette("design_choices", package = "checkinput")`. That vignette also shows
how to get a named boolean vector indicating for each element of `x` if it is
`TRUE` or `FALSE` according to the check functions.
**checkinput** also contains a
[vignette about type coercion](https://jessealderliesten.github.io/checkinput/articles/type_coercion.html)
in relation to checking function input:
`vignette("type_coercion", package = "checkinput")`.
## Function overview
The check functions in **checkinput** can be divided into groups based on the
kind of **input** for which they return `TRUE`:
- zero-length values: `is_zerolength()`
- logical values: `is_logical()`
- characters: `is_character()`, `all_characters()`, `is_path()`, `all_names()`
- numbers: `is_number()`, `all_numbers()`, `is_nonnegative()`,
`all_nonnegative()`, `is_positive()`, `is_natural()`, `all_natural()`
Besides these check functions, **checkinput** contains utility-functions:
- `make_natural()` which returns a natural number if the input is nearly equal
to such a number
- `paste_quoted()` to concatenate input to a character string with quoted
elements
## License
This project is licensed under the terms of the [MIT License](LICENSE.md).
## Citation
```{r citation, echo = FALSE, comment = ""}
citation(basename(getwd()))
```
## Contact
Please open a
[GitHub issue](https://github.com/JesseAlderliesten/checkinput/issues) if you
have suggestions to improve **checkinput**.
## Similar packages
Functions of **checkinput** use arguments to determine if special values like
`NA` and zero-length values should be allowed, making them more flexible than
functions in similar R packages that require different functions to include
these special values. Nevertheless, the following similar packages are worth
looking into:
- [**arkhe**](https://CRAN.R-project.org/package=arkhe): tools for cleaning
rectangular data
- [**assertable**](https://CRAN.R-project.org/package=assertable): verbose
assertions for tabular data (data.frames and data.tables)
- [**assertthat**](https://CRAN.R-project.org/package=assertthat): easy pre and
post assertions
- [**checkmate**](https://CRAN.R-project.org/package=checkmate): fast and
versatile argument checks
- [**chk**](https://CRAN.R-project.org/package=chk): check user-supplied
function arguments
- [**erify**](https://CRAN.R-project.org/package=erify): check arguments and
generate readable error messages