Using if
, ifelse
, and `if`
There are several ways to do if-statements in R. Golf-optimal solutions can vary a lot.
The basics
if
is for control flow. It is not vectorized, i.e. can only evaluate conditions of length 1. It requires else
to (optionally) return an else value.
ifelse
is a function. It is vectorized, and can return values of arbitrary length. Its third argument (the else value) is obligatory.*
`if`
is a function, with the same syntax as ifelse
. It is not vectorized, nor are any of the return arguments obligatory.
* It's not technically obligatory; ifelse(TRUE,x)
works just fine, but it throws an error if the third argument is empty and the condition evaluates to FALSE
. So it's only safe to use if you are sure that the condition is always TRUE
, and if that's the case, why are you even bothering with an if-statement?
Examples
These are all equivalent:
if(x)y else z # 13 bytes
ifelse(x,y,z) # 13 bytes
`if`(x,y,z) # 11 bytes
Note that the spaces around else
are not required if you are using strings directly in the code:
if(x)"foo"else"bar" # 19 bytes
ifelse(x,"foo","bar") # 21 bytes
`if`(x,"foo","bar") # 19 bytes
So far, `if`
looks to be the winner, as long as we don't have vectorized input. But what about cases where we don't care about the else condition? Say we only want to execute some code if the condition is TRUE
. For one line of code alone, if
is usually best:
if(x)z=f(y) # 11 bytes
ifelse(x,z<-f(y),0) # 19 bytes
`if`(x,z<-f(y)) # 15 bytes
For multiple lines of code, if
is still the winner:
if(x){z=f(y);a=g(y)} # 20 bytes
ifelse(x,{z=f(y);a=g(y)},0) # 27 bytes
`if`(x,{z=f(y);a=g(y)}) # 23 bytes
There's also the possibility where we do care about the else condition, and where we want to execute arbitrary code rather than return a value. In these cases, if
and `if`
are equivalent in byte count.
if(x)a=b else z=b # 17 bytes
ifelse(x,a<-b,z<-b) # 19 bytes
`if`(x,a<-b,z<-b) # 17 bytes
if(x){z=y;a=b}else z=b # 22 bytes
ifelse(x,{z=y;a=b},z<-b) # 24 bytes
`if`(x,{z=y;a=b},z<-b) # 22 bytes
if(x)a=b else{z=b;a=y} # 22 bytes
ifelse(x,a<-b,{z=b;a=y}) # 24 bytes
`if`(x,a<-b,{z=b;a=y}) # 22 bytes
if(x){z=y;a=b}else{z=b;a=y} # 27 bytes
ifelse(x,{z=y;a=b},{z=b;a=y}) # 29 bytes
`if`(x,{z=y;a=b},{z=b;a=y}) # 27 bytes
Summary
Use ifelse
when you have input of length > 1.
If you're returning a simple value rather than executing many lines of code, using the `if`
function is probably shorter than a full if
...else
statement.
If you just want a single value when TRUE
, use if
.
For executing arbitrary code, `if`
and if
are usually the same in terms of byte count; I recommend if
mainly because it's easier to read.
14The answers to this question could double as an anti-styleguide for R, given that code golf is really the only time you should do a lot of these things :-) – Andrew Brēza – 2017-08-07T18:53:14.527