Почему, если выход блока изменяется для остановки / предупреждения? - PullRequest
0 голосов
/ 29 октября 2018

Резюме: почему четвертый блок ниже (с круглыми скобками вокруг блока 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

Создано в 2018-10-29 пакетом представ. (v0.2.0).

1 Ответ

0 голосов
/ 29 октября 2018

Мы можем использовать пакет lobstr на github для сравнения абстрактных синтаксических деревьев, возвращаемых, когда 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 только в первом случае

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...