# R function for a timer with a beep

I wrote a quick timer function that depends on the beepr package to provide the sound effect at the end of the time. I've never used a while-loop before, so I don't know if there's a more elegant way to write this (i.e., one that doesn't require repeating the same line of code twice?). I'd appreciate knowing if there is a better way:

timer <- function(interval, units) {
require(beepr)
t0 <- Sys.time()
stopwatch <- round(as.double(difftime(Sys.time(), t0, u = units)))
while(stopwatch < interval){
stopwatch <- round(as.double(difftime(Sys.time(), t0, u = units)))
}
beep(2)
}

timer(5, "secs")


To avoid repeating code, you could have used:

done <- FALSE
while(!done){
done <- round(as.double(difftime(Sys.time(), t0, u = units))) >= interval
}


Note however that a for loop is quite taxing on your CPU. Instead, you should use the friendlier Sys.sleep function. It takes a number of seconds as input:

timer <- function(num_sec) {
Sys.sleep(num_sec)
if (require(beepr)) beep(2) else message("DONE!")
}


Notice how I improved your code regarding the use of require, since you had not accounted for the possibility that your user does not have the beepr package installed. If you want to make the beepr package a requirement, then calling library(beepr) is prefered to require(beepr), the blog here https://yihui.name/en/2014/07/library-vs-require/ offers a nice explanation.

If you absolutely want your function to allow to pass "minutes", "days", etc. (though I would stay away from it), you can do:

timer <- function(interval, units = c("secs", "mins", "hours", "days", "weeks")) {
units <- match.arg(units)
num_sec <- interval * switch(units, secs = 1, mins = 60, hours = 3600,
days = 86400, weeks = 604800)
Sys.sleep(num_sec)
if (require(beepr)) beep(2) else message("DONE!")
}