Advanced error handling: systematically try a range of handlers

谁说胖子不能爱 提交于 2019-12-10 20:08:19

问题


Another follow up to this and this.

Actual question

Question 1

Upon running into some condition (say a simpleError), how can I invoke a respective restart handler that systematically tests a range of actual handler functions until one is found that does not result in another condition? If the last available handler has been tried, the default abortion restart handler should be invoked (invokeRestart("abort")). The implementation should allow for a flexible specification of the actual "handler suite" to use.

Question 2

I don't understand how a) the a test function that is specified alongside a restart handler works and b) where it would make sense to use it. Any suggestions? A short example would be great!

The help page of withRestarts says:

The most flexible form of a restart specification is as a list that can include several fields, including handler, description, and test. The test field should contain a function of one argument, a condition, that returns TRUE if the restart applies to the condition and FALSE if it does not; the default function returns TRUE for all conditions.


For those interested in more details

Below you'll find my first approach with respect to question 1, but I'm sure there's something much more cleaner/more straight-forward out there ;-)

foo <- function(x, y) x + y
fooHandled <- function(
    x,
    y,
    warning=function(cond, ...) {
        invokeRestart("warninghandler", cond=cond, ...)},
    error=function(
        cond, 
        handlers=list(
            expr=expression(x+"b"),
            expr=expression(x+"c"),
            expr=expression(x+100)
        ),
        ...) {
            invokeRestart("errorhandler", cond=cond, handlers=handlers, ...)
        }
) {
    expr <- expression(foo(x=x, y=y))
    withRestarts(
        withCallingHandlers(
            expr=eval(expr),
            warning=warning,
            error=error 
        ),
        warninghandler=function(cond, ...) warning(cond),
        errorhandler=function(cond, handlers, ...) {
            idx <- 1
            do.continue <- TRUE
            while (do.continue) {
                message(paste("handler:", idx))
                expr    <- handlers[[idx]]                            
                out     <- withRestarts(
                    tryCatch(
                        expr=eval(expr),
                        error=function(cond, ...) {
                            print(cond)
                            message("trying next handler ...")
                            return(cond)
                        }
                    )
                )
                idx <- idx + 1
                do.continue <- inherits(out, "simpleError")
            }
            return(out)
        }
    )
}

> fooHandled(x=1, y=1)    
[1] 2
> fooHandled(x=1, y="a")
handler: 1
<simpleError in x + "b": non-numeric argument to binary operator>
trying next handler ...
handler: 2
<simpleError in x + "c": non-numeric argument to binary operator>
trying next handler ...
handler: 3
[1] 101

EDIT

I'd also be interested in hearing how to substitute the tryCatch part with a withCallingHandlers part. Seems like withCallingHandlers() doesn't really return anything that could be picked up to determine the value of do.continue

来源:https://stackoverflow.com/questions/15440226/advanced-error-handling-systematically-try-a-range-of-handlers

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