3

另一个跟进thisthis

实际问题

问题 1

在遇到某种情况(比如 a simpleError)时,我如何调用一个相应的重新启动处理程序来系统地测试一系列实际处理程序函数,直到找到一个不会导致另一种情况的处理程序?如果尝试了最后一个可用的处理程序,则应调用默认的中止重启处理程序 ( invokeRestart("abort"))。该实现应该允许对要使用的实际“处理程序套件”进行灵活规范。

问题2

我不明白 a) 与重启处理程序一起指定的测试函数是如何工作的,以及 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

4

0 回答 0