rfunctionvariable-assignmentexpression-evaluation

return value of if statement in r


So, I'm brushing up on how to work with data frames in R and I came across this little bit of code from 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"
}

Apparently, this assigns the strings (character vectors?) in the if and else statements to input based on the conditional. How is this working? It seems like magic. I am hoping to find somewhere in the official R documentation that explains this.

From other languages I would have just done:

if (file.exists("flights14.csv")) {
   input <- "flights14.csv"
} else {
  input <- "https://raw.githubusercontent.com/Rdatatable/data.table/master/vignettes/flights14.csv"
}

or in R there is ifelse which also seems designed to do exactly this, but somehow that first example also works. I can memorize that this works but I'm wondering if I'm missing the opportunity to understand the bigger picture about how R works.


Solution

  • From the documentation on the ?Control help page under "Value"

    if returns the value of the expression evaluated, or NULL invisibly if none was (which may happen if there is no else).

    So the if statement is kind of like a function that returns a value. The value that's returned is the result of either evaulating the if or the then block. When you have a block in R (code between {}), the brackets are also like a function that just return the value of the last expression evaluated in the block. And a string literal is a valid expression that returns itself

    So these are the same

    x <- "hello"
    x <- {"hello"}
    x <- {"dropped"; "hello"}
    x <- if(TRUE) {"hello"}
    x <- if(TRUE) {"dropped"; "hello"}
    x <- if(TRUE) {"hello"} else {"dropped"}
    

    And you only really need blocks {} with if/else statements when you have more than one expression to run or when spanning multiple lines. So you could also do

    x <- if(TRUE) "hello" else "dropped"
    x <- if(FALSE) "dropped" else "hello"
    

    These all store "hello" in x