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")

これにより、明示的な設定メソッドを介してフィールドに間違った値を設定しようとすると、次のエラーが発生します。

> 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()(AFAIUなどを介して情報を追加できるようにするために必要な)を介してエラーメッセージを強制すると、エラーメッセージが途切れることがpaste()あるようです。

  4. <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 に答える