#r #function #variable-assignment #expression-evaluation
#r #функция #переменная-присвоение #выражение-вычисление
Вопрос:
Итак, я рассказываю о том, как работать с фреймами данных в R, и я наткнулся на этот небольшой фрагмент кода из https://cloud.r-project.org/web/packages/data.table/vignettes/datatable-intro.html :
input <- if (file.exists("flights14.csv")) {
"flights14.csv"
} else {
"https://raw.githubusercontent.com/Rdatatable/data.table/master/vignettes/flights14.csv"
}
По-видимому, это присваивает строки (символьные векторы?) в операторах if и else to input
основано на условном. Как это работает? Это похоже на волшебство. Я надеюсь найти где-нибудь в официальной документации R, которая объясняет это.
С других языков я бы просто сделал:
if (file.exists("flights14.csv")) {
input <- "flights14.csv"
} else {
input <- "https://raw.githubusercontent.com/Rdatatable/data.table/master/vignettes/flights14.csv"
}
или в R есть ifelse
который также, кажется, предназначен для выполнения именно этого, но каким-то образом этот первый пример также работает. Я могу запомнить, что это работает, но мне интересно, не упускаю ли я возможность понять общую картину того, как работает R.
Ответ №1:
Из документации на ?Control
странице справки в разделе «Значение»
if
возвращает значение вычисленного выражения илиNULL
невидимо, если такового не было (что может произойти, если другого выражения нет).
Таким образом, if
инструкция похожа на функцию, которая возвращает значение. Возвращаемое значение является результатом либо удаления if
, либо then
блока. Когда у вас есть блок в R (код между {}
), скобки также похожи на функцию, которая просто возвращает значение последнего выражения, вычисленного в блоке. А строковый литерал — это допустимое выражение, которое возвращает само себя
Таким образом, это одно и то же
x <- "hello"
x <- {"hello"}
x <- {"dropped"; "hello"}
x <- if(TRUE) {"hello"}
x <- if(TRUE) {"dropped"; "hello"}
x <- if(TRUE) {"hello"} else {"dropped"}
И вам действительно нужны блоки {}
с операторами if / else только тогда, когда у вас есть более одного выражения для запуска или когда вы занимаете несколько строк. Таким образом, вы также могли бы сделать
x <- if(TRUE) "hello" else "dropped"
x <- if(FALSE) "dropped" else "hello"
Все они хранят «hello» в x
Ответ №2:
На самом деле вы ничего не упускаете из виду в «общей картине» в R. if
Функция R нетипична как по сравнению с другими языками, так и по сравнению с типичным поведением R. В отличие от большинства функций в R, которые требуют присвоения их выходных данных «символу», то есть собственному имени R, if
позволяет присваивать, которые происходят в пределах его последующих или альтернативных блоков кода, в глобальной среде. Большинство функций возвращали бы только окончательную оценку, в то время как все остальное, что происходило внутри тела функции, было бы собранным мусором.
Другой распространенной нетипичной функцией является for
. R for
-циклы только сохраняют эти внутренние назначения и всегда возвращают NULL. Определение языка R называет эти нетипичные функции R «управляющими структурами». Смотрите раздел 3.3. На моей машине (и я подозреваю, что на большинстве Linux-устройств) этот документ установлен по адресу: http://127.0.0.1:10731/help/doc/manual/R-lang.html#Control-structures . Если вы используете другую ОС, то, вероятно, в вашей IDE есть выпадающее меню справки, в котором будет указатель на него. В документе справки W они называются «конструкциями потока управления», а страница справки находится по адресу ?Control
. Обратите внимание, что необходимо заключать эти термины в кавычки, когда вы хотите получить доступ к этой странице справки, используя одно из этих имен, поскольку они являются «зарезервированными словами». Таким образом, вам нужно было бы ?'if'
вместо ввода ?if
. Другие зарезервированные слова описаны на ?Reserved
странице.
?Control
?'if' ; ?'for'
?Reserved
# When you just type:
?if # and hit <return>
# you will see a " "-sign which indicateds an incomplete expression.
# you nthen need to hit <escape> to get back to a regular R interaction.
Ответ №3:
В R функции не нуждаются в явном выражении return
. Если не указано, автоматически возвращается последняя строка функции. Рассмотрим этот пример :
a <- 5
b <- 1
result <- if(a == 5) {
a <- a 1
b <- b 1
a
} else {b}
result
#[1] 6
Последняя строка в if
блоке была сохранена в result
. Аналогично, в вашем случае строковые значения «возвращаются» неявно.