Advanced error handling

笑着哭i 提交于 2019-12-02 18:24:27

This post references the inspiration for R's condition handling.

For 1., I think of simpleCondition as illustrating how one can construct custom conditions, e.g,.

 myCondition <-
    function(message, call=NULL, type=c("overflow", "underflow", "zero"))
{
    type <- match.arg(type)             # only allowed types past here
    class <- c(type, "my", "condition")
    structure(list(message = as.character(message), call = call), 
        class = class)
}

is a constructor for making custom conditions

> myCondition("oops")
<overflow: oops>
> myCondition("oops", type="underflow")
<underflow: oops>

These conditions can be used in tryCatch or withCallingHandlers

xx <- tryCatch({
    signalCondition(myCondition("oops", type="underflow"))
}, underflow=function(e) {
    message("underflow: ", conditionMessage(e))
    NA # return value, assigned to xx
})

These are S3 classes so can have a linear hierarchy -- bad and worse are both subclasses of error.

myError <-
    function(message, call=NULL, type=c("bad", "worse"))
{
    type <- match.arg(type)
    class <- c(type, "error", "condition")
    structure(list(message=as.character(message), call=call),
              class=class)
}

One might also create an error that extends the 'simpleError' S3 class as cond <- simpleError("oops"); class(cond) = c("myerr", class(cond)

With tryCatch we just get access to a single handler, the first (in the sense described on ?tryCatch) to match the class of condition

tryCatch({
    stop(myError("oops", type="worse"))
}, bad = function(e) {
    message("bad error: ", conditionMessage(e))
}, worse = function(e) {
    message("worse error: ", conditionMessage(e))  # here's where we end up
}, error=function(e) {
    message("error: ", conditionMessage(e))
})

With withCallingHandlers we have the opportunity to hit multiple handlers, provided we don't invoke a restart

withCallingHandlers({
    stop(myError("oops", type="bad"))
}, bad = function(e) {                             # here...
    message("bad error: ", conditionMessage(e))
}, worse = function(e) {
    message("worse error: ", conditionMessage(e))
}, error=function(e) {                             # ...and here...
    message("error: ", conditionMessage(e))
})                                                 # ...and top-level 'error'

withCallingHandlers({
    x <- 1
    warning(myError("oops", type="bad"))
    "OK"
}, bad = function(e) {                     # here, but continue at the restart
    message("bad warning: ", conditionMessage(e))
    invokeRestart("muffleWarning")
}, worse = function(e) {
    message("worse warning: ", conditionMessage(e))
})

I'm not so sure about your question 2; I think this is the situation that calling handlers are designed to address -- the entire frame where the condition was invoked is poised waiting to continue, once you invoke the restart.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!