Skip to content

Commit

Permalink
Implement stabilize_lgl(). (#36)
Browse files Browse the repository at this point in the history
Closes #28.

Also switched to to_lgl_scalar() wherever possible internally, and abstracted the stabilize_cls functions.
  • Loading branch information
jonthegeek committed Aug 10, 2023
1 parent 485954e commit 77c91a2
Show file tree
Hide file tree
Showing 23 changed files with 486 additions and 45 deletions.
2 changes: 2 additions & 0 deletions NAMESPACE
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ export(stabilize_arg)
export(stabilize_arg_scalar)
export(stabilize_int)
export(stabilize_int_scalar)
export(stabilize_lgl)
export(stabilize_lgl_scalar)
export(to_int)
export(to_int_scalar)
export(to_lgl)
Expand Down
2 changes: 1 addition & 1 deletion R/check.R
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
allow_na = TRUE,
x_arg = rlang::caller_arg(x),
call = rlang::caller_env()) {
allow_na <- to_lgl(allow_na, allow_null = FALSE, call = call)
allow_na <- to_lgl_scalar(allow_na, allow_null = FALSE, call = call)
failures <- is.na(x)
if (allow_na || !any(failures)) {
return(invisible(NULL))
Expand Down
5 changes: 5 additions & 0 deletions R/is.R
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,11 @@
allow_null = FALSE,
call = call
)
# Can't use to_lgl_scalar because of recursion, do a one-off check.
if (vctrs::vec_size(allow_null) > 1) {
x_arg <- "allow_null"
.stop_must(msg = "must have a single {.cls logical} value.", call = call)
}

return(is.null(x) && allow_null)
}
2 changes: 2 additions & 0 deletions R/msgs_common.R
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
.stop_must <- function(msg, call, additional_msg = NULL) {
# TODO: This x_arg is a hidden argument and I don't have a good answer for how
# to get rid of it yet.
main_msg <- paste("{.arg {x_arg}}", msg)
cli::cli_abort(
c(main_msg, additional_msg),
Expand Down
47 changes: 47 additions & 0 deletions R/stabilize_arg.R
Original file line number Diff line number Diff line change
Expand Up @@ -48,3 +48,50 @@ stabilize_arg <- function(x,
)
return(x)
}

.stabilize_cls <- function(x,
to_cls_fn,
...,
to_cls_args = list(),
check_cls_value_fn = NULL,
check_cls_value_fn_args = list(),
allow_null = TRUE,
allow_na = TRUE,
min_size = NULL,
max_size = NULL,
x_arg = rlang::caller_arg(x),
call = rlang::caller_env(),
x_class = object_type(x)) {
x_arg <- force(x_arg)

x <- rlang::inject(
to_cls_fn(
x,
allow_null = allow_null,
!!!to_cls_args,
x_arg = x_arg,
call = call,
x_class = x_class
)
)
if (!is.null(check_cls_value_fn)) {
rlang::inject(
check_cls_value_fn(
x,
!!!check_cls_value_fn_args,
x_arg = x_arg, call = call
)
)
}
stabilize_arg(
x = x,
...,
allow_null = allow_null,
allow_na = allow_na,
min_size = min_size,
max_size = max_size,
x_arg = x_arg,
call = call,
x_class = x_class
)
}
43 changes: 43 additions & 0 deletions R/stabilize_arg_scalar.R
Original file line number Diff line number Diff line change
Expand Up @@ -30,3 +30,46 @@ stabilize_arg_scalar <- function(x,
.check_na(x, allow_na = allow_na, x_arg = x_arg, call = call)
return(x)
}

.stabilize_cls_scalar <- function(x,
to_cls_fn,
...,
to_cls_args = list(),
check_cls_value_fn = NULL,
check_cls_value_fn_args = list(),
allow_null = TRUE,
allow_na = TRUE,
x_arg = rlang::caller_arg(x),
call = rlang::caller_env(),
x_class = object_type(x)) {
x_arg <- force(x_arg)

x <- rlang::inject(
to_cls_fn(
x,
allow_null = allow_null,
!!!to_cls_args,
x_arg = x_arg,
call = call,
x_class = x_class
)
)
if (!is.null(check_cls_value_fn)) {
rlang::inject(
check_cls_value_fn(
x,
!!!check_cls_value_fn_args,
x_arg = x_arg, call = call
)
)
}
stabilize_arg_scalar(
x = x,
...,
allow_null = allow_null,
allow_na = allow_na,
x_arg = x_arg,
call = call,
x_class = x_class
)
}
30 changes: 12 additions & 18 deletions R/stabilize_int.R
Original file line number Diff line number Diff line change
Expand Up @@ -41,31 +41,25 @@ stabilize_int <- function(x,
x_arg = rlang::caller_arg(x),
call = rlang::caller_env(),
x_class = object_type(x)) {
x_arg <- force(x_arg)

x <- to_int(
.stabilize_cls(
x,
to_cls_fn = to_int,
to_cls_args = list(
coerce_character = coerce_character,
coerce_factor = coerce_factor
),
check_cls_value_fn = .check_value_int,
check_cls_value_fn_args = list(
min_value = min_value, max_value = max_value
),
allow_null = allow_null,
coerce_character = coerce_character,
coerce_factor = coerce_factor,
x_arg = x_arg,
call = call,
x_class = x_class
)
.check_value_int(
x,
min_value = min_value, max_value = max_value,
x_arg = x_arg, call = call
)
stabilize_arg(
x = x,
...,
allow_na = allow_na,
min_size = min_size,
max_size = max_size,
x_arg = x_arg,
call = call,
x_class = x_class
x_class = x_class,
...
)
}

Expand Down
34 changes: 14 additions & 20 deletions R/stabilize_int_scalar.R
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@
#' stabilize_int_scalar(1L)
#' stabilize_int_scalar("1")
#' try(stabilize_int_scalar(1:10))
#' try(stabilize_int_scalar(NULL))
#' stabilize_int_scalar(NULL)
#' try(stabilize_int_scalar(NULL, allow_null = FALSE))
stabilize_int_scalar <- function(x,
...,
allow_null = TRUE,
Expand All @@ -24,29 +25,22 @@ stabilize_int_scalar <- function(x,
x_arg = rlang::caller_arg(x),
call = rlang::caller_env(),
x_class = object_type(x)) {
x_arg <- force(x_arg)

x <- to_int(
.stabilize_cls_scalar(
x,
allow_null = FALSE,
coerce_character = coerce_character,
coerce_factor = coerce_factor,
x_arg = x_arg,
call = call,
x_class = x_class
)
.check_value_int(
x,
min_value = min_value, max_value = max_value,
x_arg = x_arg, call = call
)
stabilize_arg_scalar(
x = x,
...,
to_cls_fn = to_int,
to_cls_args = list(
coerce_character = coerce_character,
coerce_factor = coerce_factor
),
check_cls_value_fn = .check_value_int,
check_cls_value_fn_args = list(
min_value = min_value, max_value = max_value
),
allow_null = allow_null,
allow_na = allow_na,
x_arg = x_arg,
call = call,
x_class = x_class
x_class = x_class,
...
)
}
44 changes: 44 additions & 0 deletions R/stabilize_lgl.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
#' Ensure a logical argument meets expectations
#'
#' Check a logical argument to ensure that it meets expectations, coercing it
#' to logical where possible. If the argument does not meet the requirements,
#' the user will receive an informative error message. Note that [to_lgl()] is a
#' faster version of this function with fewer options.
#'
#' @inheritParams .coerce-params
#' @inheritParams to_lgl
#'
#' @return The argument as a logical vector.
#' @export
#'
#' @examples
#' stabilize_lgl(c(TRUE, FALSE, TRUE))
#' stabilize_lgl("true")
#' stabilize_lgl(NULL)
#' try(stabilize_lgl(NULL, allow_null = FALSE))
#' try(stabilize_lgl(c(TRUE, NA), allow_na = FALSE))
#' try(stabilize_lgl(letters))
#' try(stabilize_lgl(c(TRUE, FALSE, TRUE), min_size = 5))
#' try(stabilize_lgl(c(TRUE, FALSE, TRUE), max_size = 2))
stabilize_lgl <- function(x,
...,
allow_null = TRUE,
allow_na = TRUE,
min_size = NULL,
max_size = NULL,
x_arg = rlang::caller_arg(x),
call = rlang::caller_env(),
x_class = object_type(x)) {
.stabilize_cls(
x,
to_cls_fn = to_lgl,
allow_null = allow_null,
allow_na = allow_na,
min_size = min_size,
max_size = max_size,
x_arg = x_arg,
call = call,
x_class = x_class,
...
)
}
34 changes: 34 additions & 0 deletions R/stabilize_lgl_scalar.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
#' Ensure a logical argument meets expectations and is length-1
#'
#' This function is equivalent to [stabilize_lgl()], but it is optimized to
#' check for length-1 logical vectors.
#'
#' @inheritParams stabilize_lgl
#'
#' @return `x`, unless one of the checks fails.
#' @export
#'
#' @examples
#' stabilize_lgl_scalar(TRUE)
#' stabilize_lgl_scalar("TRUE")
#' try(stabilize_lgl_scalar(c(TRUE, FALSE, TRUE)))
#' stabilize_lgl_scalar(NULL)
#' try(stabilize_lgl_scalar(NULL, allow_null = FALSE))
stabilize_lgl_scalar <- function(x,
...,
allow_null = TRUE,
allow_na = TRUE,
x_arg = rlang::caller_arg(x),
call = rlang::caller_env(),
x_class = object_type(x)) {
.stabilize_cls_scalar(
x,
to_cls_fn = to_lgl,
allow_null = allow_null,
allow_na = allow_na,
x_arg = x_arg,
call = call,
x_class = x_class,
...
)
}
8 changes: 6 additions & 2 deletions R/to_int.R
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,11 @@ to_int.character <- function(x,
x_arg = rlang::caller_arg(x),
call = rlang::caller_env(),
x_class = object_type(x)) {
coerce_character <- to_lgl(coerce_character, allow_null = FALSE, call = call)
coerce_character <- to_lgl_scalar(
coerce_character,
allow_null = FALSE,
call = call
)
if (coerce_character) {
cast <- suppressWarnings(as.integer(x))
x_na <- is.na(x)
Expand Down Expand Up @@ -103,7 +107,7 @@ to_int.factor <- function(x,
x_arg = rlang::caller_arg(x),
call = rlang::caller_env(),
x_class = object_type(x)) {
coerce_factor <- to_lgl(coerce_factor, allow_null = FALSE, call = call)
coerce_factor <- to_lgl_scalar(coerce_factor, allow_null = FALSE, call = call)
if (coerce_factor) {
return(
to_int(
Expand Down
4 changes: 3 additions & 1 deletion R/to_lgl.R
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
#' Coerce an argument to logical
#'
#' If a value can be coerced to a logical without losing information, do so
#' silently. Otherwise throw an informative error.
#' silently. Otherwise throw an informative error. This function is equivalent
#' to [stabilize_lgl()] with all of the additional arguments set to their
#' default values, but should be faster.
#'
#' @inheritParams .coerce-params
#'
Expand Down
2 changes: 1 addition & 1 deletion R/to_null.R
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ to_null <- function(x,
allow_null = TRUE,
x_arg = rlang::caller_arg(x),
call = rlang::caller_env()) {
allow_null <- to_lgl(allow_null, allow_null = FALSE, call = call)
allow_null <- to_lgl_scalar(allow_null, allow_null = FALSE, call = call)
if (allow_null) {
return(NULL)
}
Expand Down
3 changes: 2 additions & 1 deletion man/stabilize_int_scalar.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit 77c91a2

Please sign in to comment.