23. Try { } - RobertMakyla/scalaWiki GitHub Wiki

source: http://danielwestheide.com/blog/2012/12/26/the-neophytes-guide-to-scala-part-6-error-handling-with-try.html

try{} catch{}

try {
    // sth risky
} catch {
    case e:Throwable => log.error(e.getMessage)
}

It's like in JAVA - It's not a functional way !!!

Try

Either[A] - might be Left[A] or Right[A]
Option[A] - might be Some[A] or None
Try[A]    - might be Success[A] or Failure[A]

   Success[A] - contains A : Success(A)
   Failure[A] - contains Throwable: Failure(Throwable)

We should enclose a risky code in Try() and this returns Try[A]

import scala.util.Try
import java.net.URL
def parseURL(url: String): Try[URL] = Try( new URL(url) )

parseURL("blee") match {
  case Success(goodUrl)                   => println(s"url is ok : $goodUrl")
  case Failure(me: MalformedURLException) => println(s"malformed : ${me.getMessage}")
  case Failure(t)                         => println(s"throwable : ${t.getMessage}")
}

parseURL("blee").isSuccess  // --> false
parseURL("blee").toOption   // --> Option[URL]

parseURL("blee").map( url => url.getHost)  // --> Failure(MalformedURLException)

Try.map

I can chain many map() which returns Try[Try[Try[A]]] :

def inputStreamForURL(url: String): Try[Try[Try[InputStream]]] = parseURL(url).map { u =>
    Try(u.openConnection()).map(conn => Try(conn.getInputStream))
}

Try.flatmap

I can chain many flatmap() which returns Try[A] :

def inputStreamForURL(url: String): Try[InputStream] = parseURL(url).flatMap { u =>
    Try(u.openConnection()).flatMap(conn => Try(conn.getInputStream))
}

###Recover

This is alternative to getOrElse() to establish returning value in case of failure

val content = parseURL("blee") recover {
  case e: MalformedURLException => URL("http://default.host.1")
  case _                        => URL("http://default.host.0")
}

Now, with recover, this will always return Success because in recover{} we show which success to return in case of failure. So we can safely call .get()

KATA flatmap/for-comprehension on Try - if each operation is throwable

import scala.util.Try
import java.net.URL
Try(new URL("http://www.google.com")).flatMap { url =>
   Try(url.openConnection()).flatMap{ conn =>
     Try(conn.getInputStream)
   }
}

or

import scala.util.Try
import java.net.URL
for{
  url  <- Try(new URL("http://www.google.com"))
  conn <- Try(url.openConnection())
  in   <- Try(conn.getInputStream )
} yield in

możnaby zrobić tak pisanie do pliku:

import java.io.FileWriter
Try(new FileWriter("C:\\Temp\\file.txt")).flatMap { fw =>
  Try{fw.write("content");fw.close()}
}

tylko tu jest problem że jak sie wywali na fw.write() to nie zamknie fw.close(), nawet jak zrobimy na tym ostatnim Try.recover to też nie zamknie bo nie ma uchwytu na fw, więc try{}finally{} jest tu niezbędne:

KATA Try and Writing to file:

def aroundWriter(fw: FileWriter)(f: FileWriter => Unit) = try f(fw) finally fw.close()
 
Try(
  aroundWriter(new FileWriter(file, false)) {
    fw => fw.write("some content")
  }
) match {
  case Success(_) => \/-(())
  case Failure(e) => -\/(e.getMessage)
}