我最近提出了this question,幸好有人指出withRestarts()
这对我来说非常棒和强大:-)现在我急于更详细地了解R的错误处理能力。< / p>
simpleCondition()
的推荐用法是什么?从来没有使用它,但我认为它可能有助于设计实际上是“真实”条件的自定义错误和警告。是否可以用于构建特定条件的数据库,以获取特定的处理程序?save.image()
,但是AFAIU,这不会存储搜索路径的“状态”(search()
或searchpaths()
)。两个代码示例
withRestarts
依赖于此blog post 我很感激有关如何做得更好的任何意见/建议; - )
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")
答案 0 :(得分:12)
This帖子引用了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'S2类扩展为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不太确定;我认为这是调用处理程序旨在解决的情况 - 一旦调用重新启动,调用条件的整个框架将等待继续。