有没有办法直接扩展/扩充/覆盖当我自己编写的函数调用失败时抛出的原始错误消息(即函数)来自基础R 和贡献包)?
考虑以下参考类:
setRefClass("A", fields=list(x1="character"))
指定正确的值时没有错误:
new("A", x1="Hello World!")
指定错误值时产生的错误:
> new("A", x1=TRUE)
Error: invalid assignment for reference class field 'x1', should be from class "character" or a subclass (was class "logical")
现在,我想要包含实际“导致问题”的类的信息。
也许这看起来像这样:
Error: Field assignment error in class 'A':
Invalid assignment for reference class field 'x1', should be from class "character" or a subclass (was class "logical")
我目前关于实现某些事情的解决方法通常是这样的:
setRefClass("A",
fields=list(x1="character"),
methods=list(
setField=function(field, value) {
tryCatch(
.self$field(name=field, value=value),
warning=function(cond) {
message(cond)
.self$field(field=field, value=value)
},
error=function(cond) {
stop(paste0("Field assignment error in class '",
class(.self), "'\n"),
"ORIGINAL ERROR:\n", as.character(cond)
)
}
)
}
)
)
首先实例化“空白”对象
x <- new("A")
当尝试通过显式setter方法向字段设置错误值时,这会给我以下错误:
> x$setField(field="x1", value=TRUE)
Error in value[[3L]](cond) : Field assignment error in class 'A'
ORIGINAL ERROR:
Error: invalid assignment for reference class field 'x1', should be from class "character" or a subclass (was class "logical")
由于以下原因,我不喜欢它:
这只是一些额外信息的代码,而tryCatch()
部分使代码更难阅读。
由于tryCatch()
的性质,AFAIU如果我期望某种“常规”行为,我也有义务将.self$field(field=field, value=value)
声明放在warning()
函数中(即“即使有警告,仍然设置字段值”)。这是重复的代码。
在我看来,通过as.character()
(为了能够通过paste()
等添加信息所必需的AFAIU)强制错误消息有时会删除错误消息。
这样我就不得不通过显式setter函数(<obj>$setField(<field>, <value>)
)设置我的字段值,而不是通过“内置”initialize
函数设置它们({{1 }})
答案 0 :(得分:1)
编写一个有用的构造函数是有用的,包括与用户预期的参数类型进行通信,提供适当的默认值,以及检查/强制参数值
.A <- setRefClass("A", fields=list(x1="character"))
A <- function(x1=character(), ...) {
if (!is.character(x1))
stop("field 'x1' should be character()")
.A(x1=x1, ...)
}
通常使用withCallingHandler
并调用重启
withCallingHandlers({
warning("oops")
1
}, warning=function(warn) {
warning("I'm handling: ", conditionMessage(warn), call.=FALSE)
invokeRestart("muffleWarning")
})
带输出
[1] 1
Warning message:
I'm handling: oops
使用withCallingHandlers(tryCatch())
范例来处理警告(重启)和错误。
conditionMessage()
访问条件消息。