Useful if you employ non-user level sub-functions within user-level functions or if you want string interpolation in error messages. When an error is thrown in the sub function, the error message will integrate the call of the user-level function, which is more informative and appropriate for the user. It offers a similar functionality for warning.

stop_up(..., up = 1, msg = NULL, envir = parent.frame(), verbatim = FALSE)

stopi(..., envir = parent.frame())

warni(..., envir = parent.frame(), immediate. = FALSE)

warn_up(
  ...,
  up = 1,
  immediate. = FALSE,
  envir = parent.frame(),
  verbatim = FALSE
)

Arguments

...

Objects that will be coerced to character and will compose the error message.

up

The number of frames up, default is 1. The call in the error message will be based on the function up frames up the stack. See examples. If you have many calls to stop_up/warn_up with a value of up different than one, you can use set_up to change the default value of up within the function.

msg

A character vector, default is NULL. If provided, this message will be displayed right under the error message. This is mostly useful when the text contains formatting because the function stop used to send the error message erases any formatting.

envir

An environment, default is parent.frame(). Only relevant if the error/warning message contains interpolation (interpolation is performed with stringmagic). It tells where the variables to be interpolated should be found. In general you should not worry about this argument.

verbatim

Logical scalar, default is FALSE. By default the error/warning message allows variable interpolation with stringmagic. To disable interpolation, use verbatim = TRUE.

immediate.

Whether the warning message should be prompted directly. Defaults to FALSE.

Details

These functions are really made for package developers to facilitate the good practice of providing informative user-level error/warning messages.

The error/warning messages allow variable interpolation by making use of stringmagic's interpolation.

Functions

  • stopi(): Error messages with string interpolation

  • warni(): Warnings with string interpolation

  • warn_up(): Warnings at the level of user-level functions

See also

For general argument checking, see check_arg() and check_set_arg().

Author

Laurent Berge

Examples


# We create a main user-level function
# The computation is done by an internal function
# Here we compare stop_up with a regular stop

main_function = function(x = 1, y = 2){
  my_internal_function(x, y)
}

my_internal_function = function(x, y){
  if(!is.numeric(x)){
    stop_up("Argument 'x' must be numeric but currently isn't.")
  }

  # Now regular stop
  if(!is.numeric(y)){
    stop("Argument 'y' must be numeric but currently isn't.")
  }

  nx = length(x)
  ny = length(y)
  if(nx != ny){
    # Note that we use string interpolation with {}
    warn_up("The lengths of x and y don't match: {nx} vs {ny}.")
  }

  x + y
}

# Let's compare the two error messages
# stop_up:
try(main_function(x = "a"))
#> Error : the full stack is shown (set this off with setDreamerr_show_stack(FALSE))
#> [01] tryCatch(withCallingHandlers({
#> [02] tryCatchList(expr, classes, parentenv, handlers)
#> [03] tryCatchOne(tryCatchList(expr, names[-nh], parentenv, handlers[-nh]), names[nh], parentenv, handlers...
#> [04] doTryCatch(return(expr), name, parentenv, handler)
#> [05] tryCatchList(expr, names[-nh], parentenv, handlers[-nh])
#> [06] tryCatchOne(expr, names, parentenv, handlers[[1L]])
#> [07] doTryCatch(return(expr), name, parentenv, handler)
#> [08] withCallingHandlers({
#> [09] saveRDS(do.call(do.call, c(readRDS("C:\\Users\\berge028\\AppData\\Local\\Temp\\RtmpyexTgx\\callr-fun...
#> [10] do.call(do.call, c(readRDS("C:\\Users\\berge028\\AppData\\Local\\Temp\\RtmpyexTgx\\callr-fun-3c04235...
#> [11] (function (what, args, quote = FALSE, envir = parent.frame()) 
#> [12] (function (..., cli_colors, pkgdown_internet) 
#> [13] pkgdown::build_site(...)
#> [14] build_site_local(pkg = pkg, examples = examples, run_dont_run = run_dont_run, seed = seed, lazy = la...
#> [15] build_reference(pkg, lazy = lazy, examples = examples, run_dont_run = run_dont_run, seed = seed, ove...
#> [16] purrr::map(topics, build_reference_topic, pkg = pkg, lazy = lazy, examples_env = examples_env, run_d...
#> [17] map_("list", .x, .f, ..., .progress = .progress)
#> [18] with_indexed_errors(i = i, names = names, error_call = .purrr_error_call, call_with_cleanup(map_impl...
#> [19] withCallingHandlers(expr, error = function(cnd) {
#> [20] call_with_cleanup(map_impl, environment(), .type, .progress, n, names, i)
#> [21] .f(.x[[i]], ...)
#> [22] withCallingHandlers(data_reference_topic(topic, pkg, examples_env = examples_env, run_dont_run = run...
#> [23] data_reference_topic(topic, pkg, examples_env = examples_env, run_dont_run = run_dont_run)
#> [24] run_examples(tags$tag_examples[[1]], env = if (is.null(examples_env)) NULL else new.env(parent = exa...
#> [25] highlight_examples(code, topic, env = env)
#> [26] downlit::evaluate_and_highlight(code, fig_save = fig_save_topic, env = child_env(env), output_handle...
#> [27] evaluate::evaluate(code, child_env(env), new_device = TRUE, output_handler = output_handler)
#> [28] evaluate_call(expr, parsed$src[[i]], envir = envir, enclos = enclos, debug = debug, last = i == leng...
#> [29] timing_fn(handle(ev <- withCallingHandlers(withVisible(eval_with_user_handlers(expr, envir, enclos, ...
#> [30] handle(ev <- withCallingHandlers(withVisible(eval_with_user_handlers(expr, envir, enclos, user_handl...
#> [31] try(f, silent = TRUE)
#> [32] tryCatch(expr, error = function(e) {
#> [33] tryCatchList(expr, classes, parentenv, handlers)
#> [34] tryCatchOne(expr, names, parentenv, handlers[[1L]])
#> [35] doTryCatch(return(expr), name, parentenv, handler)
#> [36] withCallingHandlers(withVisible(eval_with_user_handlers(expr, envir, enclos, user_handlers)), warnin...
#> [37] withVisible(eval_with_user_handlers(expr, envir, enclos, user_handlers))
#> [38] eval_with_user_handlers(expr, envir, enclos, user_handlers)
#> [39] eval(expr, envir, enclos)
#> [40] eval(expr, envir, enclos)
#> [41] try(main_function(x = "a"))
#> [42] tryCatch(expr, error = function(e) {
#> [43] tryCatchList(expr, classes, parentenv, handlers)
#> [44] tryCatchOne(expr, names, parentenv, handlers[[1L]])
#> [45] doTryCatch(return(expr), name, parentenv, handler)
#> [46] main_function(x = "a")
#> [47] my_internal_function(x, y)
#> [48] stop_up("Argument 'x' must be numeric but currently isn't."): 
#> Argument 'x' must be numeric but currently isn't.
# => the user understands that the problem is with x

# Now compare with the regular stop:
try(main_function(y = "a"))
#> Error in my_internal_function(x, y) : 
#>   Argument 'y' must be numeric but currently isn't.
# Since the user has no clue of what my_internal_function is,
#  s/he will be puzzled of what to do to sort this out

# Same with the warning => much clearer with warn_up
main_function(1, 1:2)
#> Warning: In main_function(1, 1:2):
#>  The lengths of x and y don't match: 1 vs 2.
#> [1] 2 3