1

有没有办法直接扩展/增加/覆盖当调用我自己没有编写的函数失败时抛出的原始错误消息(即来自基本 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. 由于 , AFAIU 的性质,如果我期望一些“常规”行为(即“即使有警告,字段值仍然设置”)tryCatch(),我也有义务将.self$field(field=field, value=value)语句放入函数中。warning()那是重复的代码。

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

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

4

1 回答 1

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()
于 2014-03-08T04:31:25.147 回答