Learn R Programming

rlang (version 0.1)

cnd_signal: Signal a condition

Description

Signal a condition to handlers that have been established on the stack. Conditions signalled with cnd_signal() are assumed to be benign. Control flow can resume normally once the conditions has been signalled (if no handler jumped somewhere else on the evaluation stack). On the other hand, cnd_abort() treats the condition as critical and will jump out of the distressed call frame (see rst_abort()), unless a handler can deal with the condition.

Usage

cnd_signal(.cnd, ..., .msg = NULL, .call = FALSE, .mufflable = TRUE)

cnd_abort(.cnd, ..., .msg = NULL, .call = FALSE, .mufflable = FALSE)

Arguments

.cnd

Either a condition object (see new_cnd()), or the name of a s3 class from which a new condition will be created.

...

Named data fields stored inside the condition object. These dots are evaluated with explicit splicing.

.msg

A string to override the condition's default message.

.call

Whether to display the call of the frame in which the condition is signalled. If TRUE, the call is stored in the call field of the condition object: this field is displayed by R when an error is issued. The call information is also stored in the .call field in all cases.

.mufflable

Whether to signal the condition with a muffling restart. This is useful to let inplace() handlers muffle a condition. It stops the condition from being passed to other handlers when the inplace handler did not jump elsewhere. TRUE by default for benign conditions, but FALSE for critical ones, since in those cases execution should probably not be allowed to continue normally.

Details

If .critical is FALSE, this function has no side effects beyond calling handlers. In particular, execution will continue normally after signalling the condition (unless a handler jumped somewhere else via rst_jump() or by being exiting()). If .critical is TRUE, the condition is signalled via base::stop() and the program will terminate if no handler dealt with the condition by jumping out of the distressed call frame.

inplace() handlers are called in turn when they decline to handle the condition by returning normally. However, it is sometimes useful for an inplace handler to produce a side effect (signalling another condition, displaying a message, logging something, etc), prevent the condition from being passed to other handlers, and resume execution from the place where the condition was signalled. The easiest way to accomplish this is by jumping to a restart point (see with_restarts()) established by the signalling function. If .mufflable is TRUE, a muffle restart is established. This allows inplace handler to muffle a signalled condition. See rst_muffle() to jump to a muffling restart, and the muffle argument of inplace() for creating a muffling handler.

See Also

abort(), warn() and inform() for signalling typical R conditions. See with_handlers() for establishing condition handlers.

Examples

Run this code
# NOT RUN {
# Creating a condition of type "foo"
cnd <- new_cnd("foo")

# If no handler capable of dealing with "foo" is established on the
# stack, signalling the condition has no effect:
cnd_signal(cnd)

# To learn more about establishing condition handlers, see
# documentation for with_handlers(), exiting() and inplace():
with_handlers(cnd_signal(cnd),
  foo = inplace(function(c) cat("side effect!\n"))
)


# By default, cnd_signal() creates a muffling restart which allows
# inplace handlers to prevent a condition from being passed on to
# other handlers and to resume execution:
undesirable_handler <- inplace(function(c) cat("please don't call me\n"))
muffling_handler <- inplace(function(c) {
  cat("muffling foo...\n")
  rst_muffle(c)
})

with_handlers(foo = undesirable_handler,
  with_handlers(foo = muffling_handler, {
    cnd_signal("foo")
    "return value"
  }))


# You can signal a critical condition with cnd_abort(). Unlike
# cnd_signal() which has no side effect besides signalling the
# condition, cnd_abort() makes the program terminate with an error
# unless a handler can deal with the condition:
# }
# NOT RUN {
cnd_abort(cnd)
# }
# NOT RUN {
# If you don't specify a .msg or .call, the default message/call
# (supplied to new_cnd()) are displayed. Otherwise, the ones
# supplied to cnd_abort() and cnd_signal() take precedence:
# }
# NOT RUN {
critical <- new_cnd("my_error",
  .msg = "default 'my_error' msg",
  .call = quote(default(call))
)
cnd_abort(critical)
cnd_abort(critical, .msg = "overridden msg")

fn <- function(...) {
  cnd_abort(critical, .call = TRUE)
}
fn(arg = foo(bar))
# }
# NOT RUN {
# Note that by default a condition signalled with cnd_abort() does
# not have a muffle restart. That is because in most cases,
# execution should not continue after signalling a critical
# condition.
# }

Run the code above in your browser using DataLab