Retry on failure: a simple higher-order function in Scala
Scala can be so beautiful in its simplicity <3
Here’s a HOF retry that runs a function that can fail N times before giving up:
def retry[R](retries: Int)(fn: => Option[R]): Option[R] = {
if (retries > 0) fn orElse retry(retries - 1)(fn) else None
}
We can obviously made it a lot more confusing using fold:
def retry[R](retries: Int)(fn: => Option[R]): Option[R] = {
if (retries > 0)
fn.fold(retry(retries - 1)(fn))(_ => fn)
else None
}
Or we can strip away all its elegance and resort to pattern matching (eww)
def retry[R](retries: Int)(fn: => Option[R]): Option[R] = {
if (retries > 0) {
fn match {
case None => retry(retries - 1)(fn)
case Some(result) => Some(result)
}
} else None
}
A way to use this is to put the retry method in its own trait and use it as follows:
object Test extends Retry { }
// will fail twice before succeeding
var failedCount = 0
Test.retry(3) {
if (failedCount < 2) {
failedCount += 1
println("fail")
None
}
else Some("yay!")
}