Rap*_*ter 14 error-handling r conditional-statements application-restart
我最近提出了这个问题,幸好有人指出withRestarts()这对我来说看起来非常棒和强大:-)现在我渴望更详细地了解R的错误处理能力.
simpleCondition()什么?从来没有使用它,但我认为它可能有助于设计实际上是"真实"条件的自定义错误和警告.它可以用于构建特定条件的数据库,具体的处理程序可用吗?save.image(),但AFAIU,这不存储搜索路径(search()或searchpaths())的"状态" .两个代码示例
withRestarts依赖于这篇博文 我很感激有关做什么更好的任何意见/建议;-)
require("forecast")
autoArimaFailsafe <- function(
    x,
    warning=function(w, ...) {
        message("autoArimaFailsafe> warning:")
        message(w)
        invokeRestart("donothing")},
    error=function(e, ...) {
        message("autoArimaFailsafe> error:")
        message(e)
        invokeRestart("abort")}
) {
    withRestarts(
        out <- tryCatch(
           {
                expr <- expression(auto.arima(x=x))
                return(eval(expr))
           },
           warning=warning,
           error=error 
        ),
        donothing=function(...) {
            return(eval(expr))
        },
        abort=function(...) {
            message("aborting")
            return(NULL)
        }
    )    
}
data(AirPassengers)
autoArimaFailsafe(x=AirPassengers)
autoArimaFailsafe(x="a")
require("forecast")
autoArimaFailsafe <- function(
    x,
    warning=function(w, ...) {
        message("autoArimaFailsafe> warning")
        invokeRestart("donothing")},
    error=function(e, ...) {
        message("autoArimaFailsafe> error")
        invokeRestart("abort")},
    condition=function(cond, ...) {
        out <- NULL
        message(cond)
        condmsg     <- conditionMessage(c=cond)
        condclass   <- class(cond)
        if (any(class(cond) == "simpleWarning")) {
            out <- warning(w=cond)
        } else if (any(class(cond) == "simpleError")) {
            out <- error(e=cond)
        } else if (any(class(cond) == "simpleCondition")) {
            if (condmsg == "invalid class: character") {
                out <- invokeRestart("forcedefault")
            }
        }
        return(out)
    }
) {
    withRestarts(
        out <- tryCatch(
           {
                expr <- expression(auto.arima(x=x))
                if (class(x) == "character") {
                    expr <- signalCondition(
                        simpleCondition("invalid class: character", 
                            call=as.call(expr))
                    )
                }
                return(eval(expr))
           },
           condition=condition
        ),
        donothing=function(...) {return(eval(expr))},
        abort=function(...) {
            message("aborting")
            return(NULL)
        },
        forcedefault=function(...) {
            data(AirPassengers)
            expr <- expression(auto.arima(x=AirPassengers))
            return(eval(expr))
        } 
    )
}
autoArimaFailsafe(x=AirPassengers)
autoArimaFailsafe(x=NULL)
autoArimaFailsafe(x="a")
Mar*_*gan 13
这篇文章引用了R的条件处理的灵感.
对于1.,我认为simpleCondition可以说明如何构建自定义条件,例如.
 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)
}
是一个用于制作自定义条件的构造函数
> myCondition("oops")
<overflow: oops>
> myCondition("oops", type="underflow")
<underflow: oops>
这些条件可用于tryCatch或withCallingHandlers
xx <- tryCatch({
    signalCondition(myCondition("oops", type="underflow"))
}, underflow=function(e) {
    message("underflow: ", conditionMessage(e))
    NA # return value, assigned to xx
})
这些是S3类,因此可以具有线性层次结构 - bad并且worse都是它们的子类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)
}
人们也可能会创建一个错误,将'simpleError'S3类扩展为 cond <- simpleError("oops"); class(cond) = c("myerr", class(cond)
随着tryCatch我们只是可以访问一个单一的处理器,第一个(在这个意义上描述?tryCatch)对类的条件相匹配
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))
})
随着withCallingHandlers我们有机会打多个处理程序,只要我们不调用重启
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))
})
我对你的问题2不太确定; 我认为这是调用处理程序旨在解决的情况 - 一旦调用重新启动,调用条件的整个框架将等待继续.
| 归档时间: | 
 | 
| 查看次数: | 1851 次 | 
| 最近记录: |