assert以嵌套方式调用时从当前函数返回消息

oxcyiej7  于 2023-03-05  发布在  其他
关注(0)|答案(1)|浏览(91)

让我用一个例子来解释。
我有两个职能:

fun1 <- function(x) {
  assertthat::assert_that(is.numeric(x), msg = 'Not a number')
  x
}

fun2 <- function(x) {
  assertthat::assert_that(x > 10, msg = 'Number not greater than 10')
  x + 10
}

他们被称为一个到另一个。

fun1(x = fun2(20))
#[1] 30

但是,如果fun2失败,我会从fun1得到消息。

fun1(x = fun2(2))

错误:不是数字
我希望从fun2本身获得消息,即'Number not greater than 10'
我怎么才能得到呢?
我知道我可以像下面这样分解函数调用,这将解决我的问题。

y <- fun2(20)
fun1(x = y)

但这是一个简化的例子,在我的真实情况下,不可能这样做,我也不想那样做。
有什么想法吗?

e4eetjau

e4eetjau1#

我对这个问题的理解是,assert_that()将省略号...传递给see_if(),而在这个函数中省略号是用eval(substitute(alist(...))捕获的。这就阻止了对fun2中的错误进行求值。错误对象是从fun2()返回的,然后根据fun1()中的条件进行检查。检查错误对象is.numeric是否正确,结果是否与预期'Not a number'一致。
避免这种情况的一种方法是评估fun2()的结果。在您的帖子中,您已经展示了一种方法,另一种方法是使用eval(bquote())提前计算fun2()的结果。下面我们使用bquote()中的.()see_if()捕获返回的错误对象之前提前计算fun2()。但我猜这不是你想要的解决方案。

fun1 <- function(x) {
  eval(bquote(assertthat::assert_that(.(is.numeric(x)), msg = 'Not a number')))
  x
}

fun2 <- function(x) {
  assertthat::assert_that(x > 10, msg = 'Number not greater than 10')
  x + 10
}

fun1(x = fun2(20))
#> [1] 30

fun1(x = fun2(5))
#> Error: Number not greater than 10

由于assert_that只是stopifnot()的直接替代品,因此更简单的方法是使用后者-错误消息并不那么糟糕:

fun1 <- function(x) {
  stopifnot("Not a number" = is.numeric(x))
  x
}

fun2 <- function(x) {
  stopifnot('Number not greater than 10' = x > 10)
  x + 10
}

fun1(x = fun2(20))
#> [1] 30

fun1(x = fun2(5))
#> Error in fun2(5): Number not greater than 10

reprex package(v2.0.1)于2023年2月27日创建

相关问题