扩展原始错误消息

时间:2014-03-08 01:15:34

标签: r error-handling reference-class

有没有办法直接扩展/扩充/覆盖当我自己编写的函数调用失败时抛出的原始错误消息(即函数)来自基础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")

由于以下原因,我不喜欢它:

  1. 这只是一些额外信息的代码,而tryCatch()部分使代码更难阅读。

  2. 由于tryCatch()的性质,AFAIU如果我期望某种“常规”行为,我也有义务将.self$field(field=field, value=value)声明放在warning()函数中(即“即使有警告,仍然设置字段值”)。这是重复的代码。

  3. 在我看来,通过as.character()(为了能够通过paste()等添加信息所必需的AFAIU)强制错误消息有时会删除错误消息。

  4. 这样我就不得不通过显式setter函数(<obj>$setField(<field>, <value>))设置我的字段值,而不是通过“内置”initialize函数设置它们({{1 }})

1 个答案:

答案 0 :(得分:1)

  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, ...)
    }
    
  2. 通常使用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())范例来处理警告(重启)和错误。

  3. 使用conditionMessage()访问条件消息。