-
Notifications
You must be signed in to change notification settings - Fork 40
Description
A user's attempt at selecting a column can fail for various reasons - currently, there are some (extremely brittle) ways to infer what went wrong.
Briefly, if we wanted to distinguish between these three types of tidyselect errors (mismatch, other evaluation error, empty):
library(rlang)
library(tidyselect)
df <- data.frame(x = 1)
selectors <- exprs(
mismatch = z,
error = stop(),
empty =
)
We know that a mismatch error is classed with a vctrs subscript oob error (as of the most recent update) and also stores the problematic selection in $i
:
err_mismatch <- catch_cnd(
eval_select(selectors$mismatch, df)
)
class(err_mismatch)
#> [1] "vctrs_error_subscript_oob" "vctrs_error_subscript"
#> [3] "rlang_error" "error"
#> [5] "condition"
err_mismatch$parent
#> NULL
err_mismatch$i
#> [1] "z"
An error from evaluating the user-supplied expression gets chained, so these errors are distinguished by having a $parent
:
err_error <- catch_cnd(
eval_select(selectors$error, df)
)
class(err_error)
#> [1] "rlang_error" "error" "condition"
err_error$parent
#> <simpleError in eval_tidy(as_quosure(expr, env), context_mask): >
err_error$i
#> NULL
Lastly, an empty selection that's promoted to an error with allow_empty = FALSE
has neither $i
nor a $parent
:
err_empty <- catch_cnd(
eval_select(selectors$empty, df, allow_empty = FALSE)
)
class(err_empty)
#> [1] "rlang_error" "error" "condition"
err_empty$parent
#> NULL
err_empty$i
#> NULL
I fully acknowledge that these are not part of the official API, so I do not mean to build on top of this pattern. Instead, I was hoping that tidyselect could throw more specific, classed errors, where possible. For example, it'd be nice for an empty selection error with allow_empty = FALSE
to look something like this:
err_empty2 <- catch_cnd(
eval_select(selectors$empty, df, allow_empty = FALSE)
)
class(err_empty2)
#> [1] "tidyselect_error_disallow_empty" "rlang_error"
#> [3] "error" "condition"
... by adding the "tidyselect_error_*"
class where the error gets thrown:
Lines 128 to 132 in fd22cc1
check_empty <- function(x, allow_empty = TRUE, call = caller_env()) { | |
if (!allow_empty && length(x) == 0) { | |
cli::cli_abort("Must select at least one item.", call = call) | |
} | |
} |
I realize that this is a non-trivial ask that probably requires a lot of deliberation, but I was curious whether this is within scope / planned to be worked on. Thanks in advance for considering!