Here’s a function that accepts a year (as a number) and returns TRUE or FALSE depending upon whether or not that year is a leap year. The logic is that leap years occur on years divisible by 4, excluding centuries, but including every fourth century. Recall that the %%
operator means remainder after division.
is_leap_year <- function(year)
{
if(year %% 4 == 0)
{
if(year %% 100 == 0)
{
if(year %% 400 == 0)
{
TRUE
} else
{
FALSE
}
} else
{
TRUE
}
} else
{
FALSE
}
}
The nested if statements make the code hard to understand, and stop the code being vectorized (it only accepts one input number at a time). Rewrite the function to make it easier to read. For bonus points, vectorize it.
It’s best to completely remove the if statements and use R’s built-in vectorization of its operators.
is_leap_year2 <- function(year)
{
yn <- year %% 4 == 0
yn[year %% 100 == 0] <- FALSE
yn[year %% 400 == 0] <- TRUE
setNames(yn, year)
}
A slightly fancier variation is to use assertive’s is_divisible_by
function.
library(assertive)
## assertive has some important changes. Read ?changes for details.
is_leap_year3 <- function(year)
{
yn <- is_divisible_by(year, 4)
yn[is_divisible_by(year, 100)] <- FALSE
yn[is_divisible_by(year, 400)] <- TRUE
setNames(yn, year)
}
Usage is as:
is_leap_year2(c(2015, 2016, 2100, 3000))
## 2015 2016 2100 3000
## FALSE TRUE FALSE FALSE
is_leap_year3(c(2015, 2016, 2100, 3000))
## There were 3 failures:
## Position Value Cause
## 1 1 2015 indivisible
## 2 3 2100
## 3 4 3000