【发布时间】:2018-02-02 21:49:21
【问题描述】:
更新:这里的问题已经结束,现在在RStudio Community Platform 讨论。
我正在尝试program defensively 在我的包开发中,使用大量输入验证。 特别是,我依赖于checkmate、testthat 等中的许多现成断言,这让生活变得更轻松(并且代码更短)。
Hadley Wickhams 的 tidyverse style guide for error messages 建议错误消息应将用户指向问题的确切根源,如下所示:
#> Error: Can't find column `b` in `.data`
(列只是一个例子,有时它可能是行或其他索引)。
我现在想知道如何在一个包中优雅且一致地实现这一点,因为许多现有的断言(来自上述包,但也包括基础 r)不会在错误中返回任何索引。
这是一个例子:
m <- matrix(data = c(0, 1, 5, -2), nrow = 2)
# arbitrary assertion
assert_positive <- function(x) {
if (any(x < 0)) {
stop(call. = FALSE,
"All numbers must be non-negative")
} else {
return(invisible(x))
}
}
# (there are *lots* of these in packages such as checkmate, testthat or assertr that should be reused)
assert_positive(m)
给予:
## Error: All numbers must be non-negative
到目前为止一切都很好,但这并没有给出所需的错误索引。
是的,我知道我可以更改上面的assert_positive() 函数来做到这一点,但我想重用checkmate、testthat 和朋友中的很多函数,所以我不能碰它们,反正它们太多了。
所以我可能应该包装这些现有的测试,比如一个简单的 for 循环:
# via for-loops
assert_positive2 <- function(x) {
for (r in 1:nrow(x)) {
res <- try(expr = assert_positive(x[r, ]), silent = TRUE)
if (inherits(x = res, what = "try-error")) {
stop(
call. = FALSE,
paste0(
"in row ",
r,
": ",
attr(x = res, which = "condition")$message,
"."
)
)
}
}
}
assert_positive2(m)
给予:
## Error: in row 2: All numbers must be non-negative.
这样就完成了工作,但是它很混乱,而且代码的表达能力也不是很强。
我也考虑过Reduce() 和try(),但这不会给出索引,任何apply() 操作也不会。
我想,最后,闭包或函数工厂将有助于将其推广到许多断言。
这感觉就像许多其他人(制作更好的错误消息)必须已经遇到的问题,所以:
什么是优雅/规范的方法?
我知道这里不是讨论和发表意见的地方;但它仍然是解决此类问题的最佳论坛,所以请不要关闭它。
【问题讨论】:
-
我已经在RStudio Community Forum 上发布了这个问题,毕竟这可能是进行这种公开讨论的更好地方。随意关闭。
标签: r error-handling assert tidyverse defensive-programming