assertthat在嵌套方式调用时,返回来自当前函数的消息。

huangapple go评论58阅读模式
英文:

assertthat return the message from the current function when called in a nested manner

问题

让我通过一个例子来解释。

我有两个函数:

fun1 <- function(x) {
  assertthat::assert_that(is.numeric(x), msg = '不是一个数字')
  x
}

fun2 <- function(x) {
  assertthat::assert_that(x > 10, msg = '数字不大于10')
  x + 10
}

它们相互调用。

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

然而,如果fun2失败,我会从fun1得到消息。

fun1(x = fun2(2))

错误: 不是一个数字

我期望从fun2本身得到消息,即'数字不大于10'

我知道我可以像下面这样分解函数调用来解决我的问题。

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

但这只是一个简化的例子。在我的实际情况中,这样做是不可能的,也不是我想要的方式。

有什么想法吗?

英文:

Let me explain with the help of an example.

I have two functions :

fun1 &lt;- function(x) {
  assertthat::assert_that(is.numeric(x), msg = &#39;Not a number&#39;)
  x
}

fun2 &lt;- function(x) {
  assertthat::assert_that(x &gt; 10, msg = &#39;Number not greater than 10&#39;)
  x + 10
}

They are called one into another.

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

However, if fun2 fails, I get message from fun1.

fun1(x = fun2(2))

>Error: Not a number

I would expect to get message from fun2 itself which is &#39;Number not greater than 10&#39;.

How can I get that?

I know I can break down the function calls like below which will resolve my issue.

y &lt;- fun2(20)
fun1(x = y)

but this is a simplified example. In my real case, it is not possible to do this nor do I want to do it in that way.

Any ideas?

答案1

得分: 1

以下是您要求的翻译部分:

我的理解是,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

创建于2023-02-27,使用 reprex 包 (v2.0.1)。

英文:

My understanding of the problem is that, assert_that() passes the ellipsis ... to see_if() and in this function the ellipsis is captured with eval(substitute(alist(...)). This prevents the error in fun2 to be evaluated. The error object is returned from fun2() and then checked against the condition in fun1(), checking whether the error object is.numeric which it isn't so the result is as expected &#39;Not a number&#39;.

One way to avoid this is to evaluate the result of fun2(). In your post you have shown one way, by using an intermediate object. Another way is to evalute the result of fun2() early using eval(bquote()). Below we use .() inside bquote() to evaluate fun2() early before the error object that is return is captured by see_if(). But I guess this is not your desired solution.

fun1 &lt;- function(x) {
  eval(bquote(assertthat::assert_that(.(is.numeric(x)), msg = &#39;Not a number&#39;)))
  x
}

fun2 &lt;- function(x) {
  assertthat::assert_that(x &gt; 10, msg = &#39;Number not greater than 10&#39;)
  x + 10
}

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

fun1(x = fun2(5))
#&gt; Error: Number not greater than 10

Since assert_that is just a drop-in replacement for stopifnot() the easier approach is to just use the latter - the error messages are not that bad:

fun1 &lt;- function(x) {
  stopifnot(&quot;Not a number&quot; = is.numeric(x))
  x
}

fun2 &lt;- function(x) {
  stopifnot(&#39;Number not greater than 10&#39; = x &gt; 10)
  x + 10
}

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

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

<sup>Created on 2023-02-27 by the reprex package (v2.0.1)</sup>

huangapple
  • 本文由 发表于 2023年2月27日 11:27:26
  • 转载请务必保留本文链接:https://go.coder-hub.com/75576541.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定