摘要:为什么下面的第四个块(带有if块的括号)可以正常工作,但会出现错误?
我要根据我正在处理的代码的日期发出条件警告/错误。具体来说,我进行一项昂贵的操作来保存一些excel文件,这需要几分钟,并且很少需要。如果我不这样做,我想得到提醒,如果在我希望有新数据的日期之后不这样做,我希望有一个错误提醒我。
下面的第一段代码工作正常,但我不想重复此消息。我尝试了第二段代码,该段代码可以根据需要准确地生成警告,但是当它应该是错误时(第三段),它返回函数stop
而不是使用参数作为参数调用stop
为warning
做过。
但是,当我将if块包装在括号中(下面的第四个块)时,它可以正常工作。为什么if
和stop
之间的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创建。
答案 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