Scala Some / None idiom parameter for functions that return Unit
I have several pairs of functions for managing a resource, for example:
def loadFile(name: String): Option[String]
def writeFile(name: String, data: String): ???
loadFile is currently implemented to return the resulting string using the Some / None option, but what about writeFile?
Like loadFile, if writeFile fails, I would like it to return a response wrapped in a nice Try or Option instead of throwing an exception or returning a null, boolean, or response code.
What are the recommended guidelines?
def writeFile(name: String, data: String): Try(Unit)
or
def writeFile(name: String, data: String): Option(Unit)
and just a successful check flag?
What's the best scala-like way to approach this?
source to share
The other answers here are roughly the same as Try[Unit]
, but require a little more boilerplate. It's about as easy as it gets (literally adding 3 letters to your function definition):
def writeFile(name: String, data: String): Try[Unit] = Try {
// do write operation that may throw an exception
}
The huge advantage Try
is that it is a monad, so you can map
and flatMap
(among other things) combine multiple Try
ops into one. Let's say you need to do 3 of these operations and either return Unit
or the first one Exception
.
val result: Try[Unit] = for {
a <- writeFile(name1, data1)
b <- writeFile(name2, data2)
c <- writeFile(name3, data3)
} yield ()
You can match the results:
result match {
case Success(_) => println("Success!")
case Failure(t) => println(s"Failure! {t.getMessage}")
}
You also have several other combinator functions as shown in the API docs .
And you can also write a more general method for re-failing as shown in the last block of code in this post .
source to share
I went with an approach that looks like this in the past.
trait Result
case object Success extends Result
case class Error(errorReason: String) extends Result
def writeFile(name: String): Result
This works well with pattern matching paradigms.
def writeFileWithRetry(name: String)(numRetries: Int = 2): Result = {
writeFile(name) match {
case e: Error =>
LOG.errorLog(s"Could not write $name: ${e.errorReason}")
if (numRetries <= 0) e else writeFileWithRetry(name)(numRetries - 1)
case r => r
}
}
source to share