为什么如果块输出因停止/警告而有所不同?

时间:2018-10-29 15:07:45

标签: r

摘要:为什么下面的第四个块(带有if块的括号)可以正常工作,但会出现错误?

我要根据我正在处理的代码的日期发出条件警告/错误。具体来说,我进行一项昂贵的操作来保存一些excel文件,这需要几分钟,并且很少需要。如果我不这样做,我想得到提醒,如果在我希望有新数据的日期之后不这样做,我希望有一个错误提醒我。

下面的第一段代码工作正常,但我不想重复此消息。我尝试了第二段代码,该段代码可以根据需要准确地生成警告,但是当它应该是错误时(第三段),它返回函数stop而不是使用参数作为参数调用stopwarning做过。

但是,当我将if块包装在括号中(下面的第四个块)时,它可以正常工作。为什么ifstop之间的warning输出是不同的?

today <- Sys.Date()

if (Sys.Date() > today) {
  stop("Not saving excel files")
} else {
  warning("Not saving excel files")
}
#> Warning: Not saving excel files

if (Sys.Date() > today) {
  stop
} else {
  warning
}("Not saving excel files")
#> Warning: Not saving excel files

if (Sys.Date() > as.character(as.Date(today) - 1)) {
  stop
} else {
  warning
}("Not saving excel files")
#> function (..., call. = TRUE, domain = NULL) 
#> {
#>     args <- list(...)
#>     if (length(args) == 1L && inherits(args[[1L]], "condition")) {
#>         cond <- args[[1L]]
#>         if (nargs() > 1L) 
#>             warning("additional arguments ignored in stop()")
#>         message <- conditionMessage(cond)
#>         call <- conditionCall(cond)
#>         .Internal(.signalCondition(cond, message, call))
#>         .Internal(.dfltStop(message, call))
#>     }
#>     else .Internal(stop(call., .makeMessage(..., domain = domain)))
#> }
#> <bytecode: 0x000000001c2fb4a0>
#> <environment: namespace:base>

(
  if (Sys.Date() > as.character(as.Date(today) - 1)) {
    stop
  } else {
    warning
  }
)("Not saving excel files")
#> Error in eval(expr, envir, enclos): Not saving excel files

reprex package(v0.2.0)于2018-10-29创建。

1 个答案:

答案 0 :(得分:2)

我们可以使用github上的lobstr包来比较R解析这些命令时返回的抽象语法树。观察差异。

lobstr::ast((if(FALSE) {stop} else {warning})("bad"))
# o-o-`(` 
# | \-o-`if` 
# |   +-FALSE 
# |   +-o-`{` 
# |   | \-stop 
# |   \-o-`{` 
# |     \-warning 
# \-"bad" 

lobstr::ast(if(FALSE) {stop} else {warning}("bad"))
# o-`if` 
# +-FALSE 
# +-o-`{` 
# | \-stop 
# \-o-o-`{` 
#   | \-warning 
#   \-"bad" 

请注意,在没有括号的情况下,用于调用函数的()仅绑定到else语句中传递的块。与()语句的结果相比,{}if的关联更紧密。加上括号可以帮助您覆盖默认的运算符优先级。

{}仅包装多个语句。考虑一下不带花括号的样子(if语句中不需要)

if(FALSE) stop else warning("bad")
# vs
(if(FALSE) stop else warning)("bad")

您可以看到,在第一种情况下,“坏”的外观应该只传递给warning