高级错误处理:系统地尝试一系列处理程序

时间:2013-03-15 19:01:39

标签: r error-handling event-handling try-catch conditional-statements

另一个跟进thisthis

实际问题

问题1

在遇到某种情况(比如simpleError)时,如何调用相应的重启处理程序,系统地测试一系列实际的处理程序函数,直到发现一个不会导致另一个条件?如果已尝试最后一个可用的处理程序,则应调用默认的abortion重新启动处理程序(invokeRestart("abort"))。实现应允许灵活地指定要使用的实际“处理程序套件”。

问题2

我不明白a)如何在重启处理程序旁边指定的 test 函数和b)使用它有意义的地方。有什么建议?一个简短的例子就是伟大的!

withRestarts的帮助页面说:

  
    

最灵活的重启规范形式是一个列表,可以包含多个字段,包括处理程序,描述和测试。测试字段应包含一个参数的函数,一个条件,如果重新启动适用于条件,则返回TRUE;如果不重用,则返回FALSE;所有条件的默认函数都返回TRUE。

  

对于那些对更多细节感兴趣的人

下面你会找到关于问题1的第一种方法,但我确信那里有更清洁/更直接的东西; - )

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

修改

我也有兴趣听取如何用tryCatch部分替换withCallingHandlers部分。好像withCallingHandlers()似乎没有真正返回任何可以用来确定do.continue

值的东西

0 个答案:

没有答案