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!")
}