Подтвердить что ты не робот

Если/else строит внутренние и внешние функции

Когда я смотрю на функции R, я часто нахожу следующую структуру:

f <- function(exp=T) {
  if (exp)
    a <- 1
  else
    a <- 2
}
f()
f(F)

Это будет работать без ошибок. Но выполнение внутреннего кода функции вызывает ошибку, так как R, вероятно, предполагает, что оператор завершается после первого присваивания a <- 1 и не может обрабатывать следующее.

exp=T
if (exp)
  a <- 1
else
  a <- 2

Теперь это имеет смысл для меня, но мне все же хотелось бы понять, почему поведение исполняемого кода отличается при выполнении внутри или вне функции.

4b9b3361

Ответ 1

Это следствие использования интерактивной оболочки (REPL) для запуска скриптов:

После первой ветки оболочка увидела полный оператор, поэтому предполагает, что вы сделали ввод. К сожалению, R использует одну и ту же оболочку для интерпретации скриптов, даже если они не введены в интерактивном режиме, поэтому даже когда вы сохраняете оператор if в файл и source его (или передаете его в R), вы получите ошибку на ветвь else.

Но следующее будет прекрасно работать:

if (exp) a <- 1 else a <- 2

Здесь интерпретатор проглатывает строку и выполняет ее.

В вашей функции можно предположить, что то же самое относится - и это так! Однако сама функция начинается с открытой скобки в вашем случае, поэтому R должен читать до тех пор, пока не найдет подходящую закрывающую фигуру. В отличие от этого, объявите эту функцию:

f <- function (exp)
    if (exp)
        a <- 1
    else
        a <- 2

В R вы можете определять функции без фигурных скобок вокруг тела. Но приведенный выше код не будет работать по той же причине, что и автономный if без брекетов. В отличие от этого, если бы я написал if в одной строке, этот код снова будет работать.

Кстати, ваша функция использует назначение переменной, которая не используется. Вы можете (должны) сделать следующее:

f <- function (exp) {
    if (exp)
        1
    else
        2
}

... и то же самое при использовании if внутри оболочки:

a <- if (exp) 1 else 2

потому что в R, if - это выражение, которое возвращает значение.

Ответ 2

Резюме:

Есть только два способа, чтобы R знал, что предложение else принадлежит к предложению if выше:

  • Весь оператор if... else (и, возможно, другие операторы) заключен в фигурные скобки;
  • Слово else появляется в той же строке, что и конец предложения if.

Доказательства:

Вышеприведенное обсуждение помогло мне, но я надеюсь, что могу предложить полезный каламбур. Да, правильно, что

f <- function (exp)
    if (exp)
        1  
    else
        2

терпит неудачу с классическим сообщением Error: unexpected 'else' in "else" из-за неуспеха R, чтобы продолжить чтение. 1. Два способа были правильно предложены для того, чтобы R продолжал читать мимо 1:

f <- function (exp) {
    if (exp)
        1  
    else
        2
}

и

f <- function (exp) if (exp) 1 else 2

Но есть еще третий способ, который еще не упоминается --- просто переместите else вверх по строке. Таким образом, следующее также работает, потому что R знает, что нужно читать за 1:

f <- function (exp)
    if (exp)
        1  else
        2

Я думаю, что ключевой момент состоит в том, чтобы либо скопировать весь элемент функции, либо убедиться, что else встречается в той же строке, что и конец предложения if, так что R знает, что нужно читать. Вот почему работает однострочное решение. Именно поэтому это работает:

f <- function (exp)
    if (exp) {
        1
    } else
        2

Но это не удается:

f <- function (exp)
    if (exp) {
        1
    }  
    else
        2

И используя более стандартную привязку тела функции, это тоже работает:

f <- function (exp) {
    if (exp) {
        1
    }  
    else
        2
}

Но независимо от того, строим ли мы функцию, это красная селедка. Важно только скобки и расположение else. Таким образом, эти работы:

{
    if (exp) {
        1
    }  
    else
        2
}


if (exp) {
    1
} else
    2

но это не удается:

if (exp) {
    1
} 
else
    2

и чтобы продемонстрировать мое утверждение 1 вверху, это работает:

{
x <- 4
if (exp) 
    1
else
    2
}