在 R 中使用 NSE 产生信息性的 `stopifnot()` 错误
Making informative `stopifnot()` errors using NSE in R
我想要提供信息 stopifnot()
错误。
我读过:
http://r-pkgs.had.co.nz/tests.html(最后关于使用 NSE 为示例打印信息性测试错误的部分似乎相关)
和
http://adv-r.had.co.nz/Computing-on-the-language.html
但我无法用简洁的代码打印信息性错误:
e <- new.env()
e$label <- c(1,2,3)
check_in_y <- function(x, z, e) {
stopifnot(eval(bquote(.(x) %in% e[[.(z)]])))
}
check_in_y(5,"label", e)
输出给出了这个(信息量不大)
Error: eval(bquote(.(x) %in% e[[.(z)]])) is not TRUE
我希望错误信息更丰富,这样说:
Error: 5 %in% e[["label"]] is not TRUE
我怎样才能让它工作?或者什么是实现我想要的最好方法
我知道我可以写一个 if condition not true 然后打印我自己的错误作为替代,但是额外的代码很麻烦。我想了解如何让 NSE 让它发挥作用。
编辑:
我采用这种方法的动机来自于阅读 hadley 的评论(在 http://r-pkgs.had.co.nz/tests.html):
However, if the expectation fails this doesn’t give very informative
output:
expect_floor_equal("year", "2008-01-01 00:00:00")
## Error: floor_date(base, unit) not equal to as.POSIXct(time, tz = "UTC")
## Mean absolute difference: 31622400
Instead you can use a little non-standard evaluation to produce
something more informative. The key is to use bquote() and eval(). In
the bquote() call below, note the use of .(x) - the contents of ()
will be inserted into the call.
expect_floor_equal <- function(unit, time) {
as_time <- function(x) as.POSIXct(x, tz = "UTC")
eval(bquote(expect_equal(floor_date(base, .(unit)), as_time(.(time)))))
}
expect_floor_equal("year", "2008-01-01 00:00:00")
## Error: floor_date(base, "year") not equal to as_time("2008-01-01 00:00:00")
stopifnot
只是
的便利函数
if(!all(condition)) stop(standard message)
对于自定义消息,只需编写代码即可。您可以用两行替换 stopifnot
调用:
check_in_y <- function(x, z, e) {
b <- bquote(.(x) %in% e[[.(z)]])
if(!eval(b)) stop(deparse(b), " is not TRUE", call. = FALSE)
}
check_in_y(5, "label", e)
# Error: 5 %in% e[["label"]] is not TRUE
CRAN 上有许多软件包可以解决有意义的错误消息问题。我从 assertthat
和 assertive
包开始,但我现在将 checkmate
用于生产代码,尤其是用于检查函数的参数。顺便说一句,checkmate
还扩展了 Hadley 的 testthat
包。
和checkmate
,
checkmate::assert_choice(5, e[["label"]])
以及
checkmate::assert_choice(5, e$label)
return错误信息:
Error: Assertion on '5' failed: Must be element of set {'1','2','3'}, but is '5'.
函数中也可以使用
check_in_y <- function(x, z, e) {
checkmate::assert_choice(x, e[[z]])
}
check_in_y(5, "label", e)
其中 return 是错误信息:
Error in check_in_y(5, "label", e) :
Assertion on 'x' failed: Must be element of set {'1','2','3'}, but is '5'.
我想要提供信息 stopifnot()
错误。
我读过: http://r-pkgs.had.co.nz/tests.html(最后关于使用 NSE 为示例打印信息性测试错误的部分似乎相关) 和 http://adv-r.had.co.nz/Computing-on-the-language.html 但我无法用简洁的代码打印信息性错误:
e <- new.env()
e$label <- c(1,2,3)
check_in_y <- function(x, z, e) {
stopifnot(eval(bquote(.(x) %in% e[[.(z)]])))
}
check_in_y(5,"label", e)
输出给出了这个(信息量不大)
Error: eval(bquote(.(x) %in% e[[.(z)]])) is not TRUE
我希望错误信息更丰富,这样说:
Error: 5 %in% e[["label"]] is not TRUE
我怎样才能让它工作?或者什么是实现我想要的最好方法
我知道我可以写一个 if condition not true 然后打印我自己的错误作为替代,但是额外的代码很麻烦。我想了解如何让 NSE 让它发挥作用。
编辑: 我采用这种方法的动机来自于阅读 hadley 的评论(在 http://r-pkgs.had.co.nz/tests.html):
However, if the expectation fails this doesn’t give very informative output:
expect_floor_equal("year", "2008-01-01 00:00:00") ## Error: floor_date(base, unit) not equal to as.POSIXct(time, tz = "UTC") ## Mean absolute difference: 31622400
Instead you can use a little non-standard evaluation to produce something more informative. The key is to use bquote() and eval(). In the bquote() call below, note the use of .(x) - the contents of () will be inserted into the call.
expect_floor_equal <- function(unit, time) { as_time <- function(x) as.POSIXct(x, tz = "UTC") eval(bquote(expect_equal(floor_date(base, .(unit)), as_time(.(time))))) } expect_floor_equal("year", "2008-01-01 00:00:00") ## Error: floor_date(base, "year") not equal to as_time("2008-01-01 00:00:00")
stopifnot
只是
if(!all(condition)) stop(standard message)
对于自定义消息,只需编写代码即可。您可以用两行替换 stopifnot
调用:
check_in_y <- function(x, z, e) {
b <- bquote(.(x) %in% e[[.(z)]])
if(!eval(b)) stop(deparse(b), " is not TRUE", call. = FALSE)
}
check_in_y(5, "label", e)
# Error: 5 %in% e[["label"]] is not TRUE
CRAN 上有许多软件包可以解决有意义的错误消息问题。我从 assertthat
和 assertive
包开始,但我现在将 checkmate
用于生产代码,尤其是用于检查函数的参数。顺便说一句,checkmate
还扩展了 Hadley 的 testthat
包。
和checkmate
,
checkmate::assert_choice(5, e[["label"]])
以及
checkmate::assert_choice(5, e$label)
return错误信息:
Error: Assertion on '5' failed: Must be element of set {'1','2','3'}, but is '5'.
函数中也可以使用
check_in_y <- function(x, z, e) {
checkmate::assert_choice(x, e[[z]])
}
check_in_y(5, "label", e)
其中 return 是错误信息:
Error in check_in_y(5, "label", e) :
Assertion on 'x' failed: Must be element of set {'1','2','3'}, but is '5'.