Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Feature Request]: Use common check for parameters c(value, min, max) #685

Open
averissimo opened this issue Feb 26, 2024 · 0 comments
Open
Labels
core enhancement New feature or request

Comments

@averissimo
Copy link
Contributor

Add an internal function to {tmg} that performs checks for numeric vectors that have the structure: c(value, min, max).

Some examples are plot_height, alpha, ...

The goal is to replace repetitive logic (represented in real examples from {tmg} below)

  checkmate::assert_numeric(plot_height, len = 3, any.missing = FALSE, finite = TRUE)
  checkmate::assert_numeric(plot_height[1], lower = plot_height[2], upper = plot_height[3], .var.name = "plot_height")
  
  # Identical to above, but it accepts null
  checkmate::assert_numeric(plot_width, len = 3, any.missing = FALSE, null.ok = TRUE, finite = TRUE)
  checkmate::assert_numeric(plot_width[1], lower = plot_width[2], upper = plot_width[3], null.ok = TRUE, .var.name = "plot_width")

  # This accepts both `alpha = 0.5` and `c(0.5, 0, 1)`
  if (length(alpha) == 1) {
    checkmate::assert_numeric(alpha, any.missing = FALSE, finite = TRUE)
  } else {
    checkmate::assert_numeric(alpha, len = 3, any.missing = FALSE, finite = TRUE)
    checkmate::assert_numeric(alpha[1], lower = alpha[2], upper = alpha[3], .var.name = "alpha")
  }

With:

  checkmate::assert(check_range_slider(plot_height), .var.name = "plot_height")

  checkmate::assert(
    .var.name = "plot_width"
    check_range_slider(plot_width),
    checkmate::check_null(plot_width)
  )

  checkmate::assert(
    .var.name = "alpha"
    check_range_slider(alpha),
    checkmate::check_number(alpha)
  )

check_range_slider source

#' Check if an argument is a bounded numeric vector of length 3
#'
#' Must follow form `c(value, min, max)` and `test_fun` must be a function that
#' supports checks on vectorized input
#' @noRd
#'
check_range_slider <- function(value,
                               lower = -Inf,
                               upper = Inf,
                               finite = TRUE,
                               test_fun = checkmate::test_numeric) {
  checkmate::assert_flag(finite)
  checkmate::assert_function(test_fun)
  checkmate::assert_number(lower)
  checkmate::assert_number(upper)

  is_numeric <- test_fun(
    value,
    len = 3,
    any.missing = FALSE
  )

  # Finite is not available in integer tests
  if ("finite" %in% names(formals(test_fun))) {
    test_fun(value, finite = finite)
  }

  is_bounded <- is_numeric && test_fun(
    value[[1]],
    len = 1,
    lower = max(lower, value[[2]]),
    upper = min(upper, value[[3]])
  )
  if (isFALSE(is_numeric) || isFALSE(is_bounded)) {
    return(
      paste(
        "Must be a numeric vector of length 3 with `c(value, min, max)`",
        "where the `value` must be between `min` and `max`"
      )
    )
  }
  TRUE
}
@averissimo averissimo added enhancement New feature or request core labels Feb 26, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
core enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

1 participant