composerr_halt | R Documentation |
The following functions allow the accumulation of multiple errors
in an internal error stack of an error handler err_h
and flushing them
all at once later on:
composerr_halt(err_h)
: Set the error handling function err_h1
to
non-flushing mode, which means that each time err_h1(msg)
is called,
the error message (msg
) gets accumulated in an internal error stack,
but no error is thrown.
composerr_flush(err_h)
: If the internal error stack is non-empty,
then create the full error message from the internal error stack and
throw an error.
If the internal error stack is empty, then do nothing.
composerr_counterr(err_h)
: Counts the number of times err_h1
was
called, since composerr_halt(err_h1)
was called.
composerr_halt(err_h) composerr_flush(err_h, action = NULL, ...) composerr_counterr(err_h)
err_h |
An error handler created with |
action |
Optional default ultimate error handler. This argument
can either be |
... |
Additional arguments, which will be passed down the error handler
cascade and ultimately be passed to the ultimate error handler
|
composerr_halt()
silently returns the passed in error handler
err_h
and composerr_flush()
silently returns the return value of
the ultimate error handler action
.
If err_h_new <- composerr(...)
was created without passing a parent
error handler to the optional argument err_h
, then
err_h_new
is a newly created error handler with the following structure
err_h_new = function(msg = NULL, action = NULL, ...)
.
Similarly, if err_h_new <- composerr(err_h = err_h_parent, ...)
was created
by passing a parent error handler err_h = err_h_parent
,
then err_h_new
is also a new error handler, which also has the structure
err_h_new = function(msg = NULL, action = NULL, ...)
, but
now it was created from a parent error handler err_h_parent
.
We now consider the latter case
err_h_new <- composerr(before, err_h_parent, after, action = action_default)
.
If the error handler gets executed with the following call
err_h_new(msg, action = action_1, ...)
,
then the following things will happen:
if the argument collapse
in composerr(...)
was set to a string, then
err_h_new
will first create a more detailed message, by first adding the
text parts defined in the arguments before
and after
and then
collapsing the created character vector using the string in collapse
as separator
msg_new <- paste(paste0(before, msg, after), collapse = collapse)
if the argument collapse
in composerr(...)
was omitted or set to NULL
,
then err_h_new
will first create a more detailed message, by first adding the
text parts defined in the arguments before
and after
, but without
collapsing the resulting vector:
msg_new <- paste0(before, msg, after)
if no argument action
is passed to err_h_new
(in this example action_1 = NULL
),
then action
will be set to the default ultimate handler
(in this example action_default
) previously assigned to err_h_new
with the argument action
.
If no default ultimate handler was previously assigned to err_h_new
,
then action
will be set to NULL
.
Finally, err_h_new
will call err_h_parent(msg_new, action = action, ...)
Since err_h_parent
is called at the end and err_h_parent
will run through
the same process, maybe calling its parent error handler, we have a
so called cascade of successive error handler calls.
The following arguments are passed down this error handler cascade:
a successively growing error message msg
(incrementally adding text parts
in front and at the end of the message).
the argument action
, which can
either be NULL
or an ultimate error handling function
used for ultimate processing of the created
error message (throw an error or a warning or do something else).
If the passed down action
argument is NULL
and at some
point in the error handling cascade there was a non-null
default ultimate error handler assigned to some error handler
in the error handler cascade, then this default ultimate error handler is
passed on instead as argument action
. Once the ultimate error handler
action
is not NULL
any more, it will remain unchanged, no matter if
there were other default ultimate error handlers assigned to other error
handlers in the error handler cascade. This means the default ultimate
error handlers of the child error handlers overwrite the default ultimate
error handlers of its ancestor error handlers.
additional arguments ...
passed to the call
err_h_new(msg, action, ...)
will be directly passed down
the error handler cascade and directly passed to the ultimate call
of the ultimate error handler action(msg_complete, ...)
.
After cascading backwards the ancestry of err_h_new
, we ultimately reach the
primal error handler, which was created first
(from scratch) and has no further parent error handler.
Let us call it err_h_primal
.
This primal error handler will do the following things:
As usual err_h_primal
will concatenate its additional text parts
before
and after
to the
passed in message. Also it will maybe collapse the resulting character
vector, depending if collapse
was set to NULL
or not.
This will give us at last the ultimate version of the error
message. Let us call it msg_complete
.
As usual err_h_primal
checks if action
is NULL
.
If so, action
is set to the default handler that was assigned
to err_h_primal
.
If the action
is still NULL
, then action
is
replaced by the stop()
function.
Ultimately err_h_primal
calls action(msg_complete, ...)
.
The result of the final call action(msg_complete, ...)
is silently
returned by err_h_new
.
Let us assume composerr_halt(err_h_new)
was called before calling
err_h_new(msg, ...)
.
In this case the error message will not be cascaded down and action
will not be called.
Instead err_h_new
will do the following things:
As usual err_h_new
will concatenate the additional message parts:
msg_new <- paste0(before, msg, after)
err_h_new
will append the resulting error message msg_new
to an internal
error stack of err_h_new
. err_stack <- c(err_stack, msg_new)
err_h_new
will return the value NULL
If later on, the function
composerr_flush(err_h_new, action = action4, ...)
is
called, then the error handler cascade will be executed as usual, but first
err_h_new
will do the following things:
If collapse != NULL
was assigned to err_h_new
, then the entire
internal error stack (a character vector holding the stored error messages),
will be collapsed to a single string:
msg_new <- paste(err_stack, collapse = collapse)
.
If collapse == NULL
was omitted when calling err_h_new <- composerr(...)
,
then the internal error stack (a character vector holding the stored error
messages) of err_h_new
will be used as msg_new
,
without collapsing it first.
As usual, if the argument action = action4
is NULL
,
then it will be replaced by
the default ultimate handler assigned to err_h_new
(in this example
action_default
).
err_h_parent(msg_new, action = action)
will be called and
the error handler cascade will continue as usual.
It is also possible to halt the error execution in the
middle of the error handler cascade, by calling
composerr_halt(err_h_middle)
,
where err_h_middle
is an error handler, that has at least one child
error handler err_h_new
.
If err_h_new
or another offspring error handler of err_h_new
gets called,
then the error handling will be cascaded down as usual until it reaches
err_h_middle
. There it will be halted and the created message will appended
to the internal error message stack of err_h_middle
.
Only by calling composerr_flush(err_h_middle)
the
error handling cascade will be continued.
It is also possible to halt the error execution at
multiple points of the error handler cascade. In order to cascade
the errors down till the end, each halted error handler must be flushed with
composerr_flush()
.
composerr()
,
composerr_get_action()
and validate_composerr()
## Not run: ##### Example-1 ##### # create general error handler err_h_parent <- composerr(before = "There are problems:\n") # create a more precise error handler listing the problems err_h_child <- composerr(" - problem-", err_h_parent) # halt `err_h_child` processing in order to collect # multiple errors composerr_halt(err_h_child) err_h_child(1) err_h_child(2:3) err_h_child(4) composerr_flush(err_h_child) # Error: There are problems: # - problem-1 # - problem-2 # - problem-3 ##### Example-2 ##### # Advanced implementation of vector multiplication # using a validation routine with **advanced error handling**: validate_numeric_vec <- function(obj, err_h) { obj_name <- deparse(substitute(obj)) err_h <- composerr(paste0("Invalid argument `", obj_name, "`: "), err_h) if (!is.numeric(obj)) err_h("Not a number.") err_h_list <- composerr(err_h = composerr("\n", err_h)) composerr_halt(err_h_list) for (i in seq_along(obj)) { err_h_item <- composerr(paste0(" - Item-", i, " is "), err_h) if (is.na(obj[i]) && !is.nan(obj[i])) err_h_item("NA.") if (is.nan(obj[i])) err_h_item("NaN.") if (is.infinite(obj[i])) err_h_item("infinite.") } composerr_flush(err_h_list) invisible(obj) } my_vec_mult2 <- function(x, y) { err_h <- composerr("In `my_vec_mult2()`: ") validate_numeric_vec(x, err_h) validate_numeric_vec(y, err_h) if (length(x) != length(y)) err_h("Vectors `x` and `y` have different length.") sum(x*y) } my_vec_mult2("a", 1:4) # Error: In `my_vec_mult2()`: Invalid argument `x`: Not a number. my_vec_mult2(c(1, NA, NaN, Inf, 5), 1:5) # Error: In `my_vec_mult2()`: Invalid argument `x`: # - Item-2 is NA. # - Item-3 is NaN. # - Item-4 is infinite. my_vec_mult2(1:5, c(NaN, 2, 3, NA, Inf)) # Error: In `my_vec_mult2()`: Invalid argument `y`: # - Item-1 is NA. # - Item-4 is NaN. # - Item-5 is infinite. my_vec_mult2(1:5, 1:4) # Error: In `my_vec_mult2()`: Vectors `x` and `y` have different length. my_vec_mult2(1:5, 1:5) 55 ## End(Not run)
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.