自分で書いていない関数の呼び出しが失敗したときにスローされる元のエラーメッセージを直接拡張/拡張/上書きする方法はありますか (つまり、ベース 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")
以下の理由で嫌いです。
ほんの少しの追加情報のための大量のコードであり、その
tryCatch()
部分によりコードがやや読みにくくなっています。tryCatch()
、AFAIUの性質上、「通常の」動作が予想される場合(つまり、「警告があったにもかかわらず、フィールド値がまだ設定されている」) 、.self$field(field=field, value=value)
ステートメントを関数内に配置する必要があります。warning()
それは重複したコードです。as.character()
(AFAIUなどを介して情報を追加できるようにするために必要な)を介してエラーメッセージを強制すると、エラーメッセージが途切れることがpaste()
あるようです。<obj>$setField(<field>, <value>)
そうすれば、「組み込み」initialize
関数 (new("A", <field>=<value>)
)を介してフィールド値を設定するのではなく、明示的なセッター関数 ( ) を介してフィールド値を設定する必要があります。