Is there a functional/Scala way to call a function repeatedly until it succeeds, while reacting to failed attempts?
Let me illustrate with an example. Suppose I want to read an integer from standard-in, and retry if the user did not in fact enter an integer.
Given this function:
def read_int(): Either[String, Int] = {
val str = scala.io.StdIn.readLine()
try {
Right(str.trim().toInt)
} catch {
case _: java.lang.NumberFormatException => Left(str)
}
}
And this anonymous functions:
val ask_for_int = () => {
println("Please enter an Int:")
read_int()
}
val handle_not_int = (s: String) => {
println("That was not an Int! You typed: " + s)
}
I would use them like this:
val num = retry_until_right(ask_for_int)(handle_not_int)
println(s"Thanks! You entered: $num")
My questions are:
- Does something like
retry_until_right
already exist in Scala? - Could it be solved with existing facilities? (Streams, Iterators, Monads, etc.)
- Do any of the FP libraries (scalaz?) offer something like this?
- Could I do anything better / more idiomatic? (*)
Thanks!
*) Apart from the snake_case. I really like it.