An alternative to match.arg() with improved
error messages via cli. Returns the first choice if x is NULL,
and supports partial matching.
Usage
match_arg(
x,
choices,
several.ok = FALSE,
ignore.case = TRUE,
.context = NULL,
.arg = rlang::caller_arg(x),
.call
)Arguments
- x
a string (or character vector if
several.ok = TRUE) to match againstchoices. IfNULL, the first element ofchoicesis returned.- choices
a character vector of valid values.
- several.ok
logical; ifTRUE,xmay contain more than one element. Defaults toFALSE.- ignore.case
logical; ifFALSE, the matching is case sensitive, and ifTRUE(the default), case is ignored.- .context
an optional character string providing context for error messages (e.g., a function or object name). Prepended to the error message when supplied before being evaluated by cli.
- .arg
the name of the argument supplied to
xto appear in error messages. The default is to extract the argument's name usingrlang::caller_arg(). Ignored if.msgis supplied.- .call
the execution environment of a currently running function, e.g.
.call = rlang::current_env(). The corresponding function call is retrieved and mentioned in error messages as the source of the error. Passed toerr(). Set toNULLto omit call information. The default is to search along the call stack for the first user-facing function in another package, if any.
Value
A character string (or vector, if several.ok = TRUE) of the matched element(s) from choices. If there is no match, an error is thrown. When several.ok = TRUE, no error is thrown if there is at least one match.
Details
Partial matching is supported via pmatch(). If no match is found, an error is thrown listing the valid choices.
Checks are run on x prior to matching: first, arg_supplied() is used to check whether x was supplied; then arg_string() (if several.ok = TRUE) or arg_character() (if several.ok = FALSE) is used to check whether x is a valid string or character vector, respectively.
When ignore.case = TRUE (the default), an initial case-sensitive match is run, and if any values in x are unmatched, a second, case-insensitive match is run. When ignore.case = FALSE, only the first match is run. This ensures that exact matches (on both content and case) are prioritized before case-insensitive matches.
See also
match.arg()for the base R versionpmatch()for the function implementing partial string matchingarg_element()for a version without type checking and that doesn't support partial matchingrlang::arg_match()for a similar rlang function that doesn't support partial matching.
Examples
f <- function(z = NULL) {
match_arg(z, c("None", "Exact", "Partial"),
ignore.case = TRUE)
}
try(f()) # "None" (first choice returned)
#> [1] "None"
try(f("partial")) # "Partial"
#> [1] "Partial"
try(f("p")) # "Partial" (partial match)
#> [1] "Partial"
try(f(c("e", "p"))) # Error: several.ok = FALSE
#> Error : `z` must be a string.
# several.ok = TRUE
g <- function(z = NULL) {
match_arg(z, c("None", "Exact", "Partial"),
several.ok = TRUE)
}
try(g("exact")) # Error: case not ignored
#> [1] "Exact"
try(g("Exact")) # "Exact"
#> [1] "Exact"
try(g(c("Exact", "Partial"))) # "Exact", "Partial"
#> [1] "Exact" "Partial"
try(g(c("Exact", "Wrong"))) # "Exact"
#> [1] "Exact"
try(g(c("Wrong1", "Wrong2"))) # Error: no match
#> Error : `z` should be at least one of "None", "Exact", or "Partial".
h <- function(z = NULL) {
match_arg(z, c("None", "Exact", "Partial"),
.context = "in {.fun h},")
}
try(h("Wrong")) # Error with context
#> Error : In `h()`, `z` should be one of "None", "Exact", or "Partial".