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?

+3


source to share


3 answers


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 .

+3


source


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
  }
}

      

+1


source


   def writeFile(name: String, data: String): Either[Exception, Unit] = try {
      doWrite(name, data)  
      Right(()) 
   } catch {
     case ex => Left(ex)
   }

    writeFile("foo", "bar") match {
       case Left(ex) => println("Failed with exception: " + ex)
       case _ => println("Success!")
    }

      

0


source







All Articles