Szukaj…


Próbować

Używanie Wypróbuj z map , getOrElse i flatMap :

import scala.util.Try

val i = Try("123".toInt)     // Success(123)
i.map(_ + 1).getOrElse(321)  // 124

val j = Try("abc".toInt)     // Failure(java.lang.NumberFormatException)
j.map(_ + 1).getOrElse(321)  // 321

Try("123".toInt) flatMap { i =>
  Try("234".toInt)
    .map(_ + i)
}                            // Success(357)

Używanie Try z dopasowaniem wzoru:

Try(parsePerson("John Doe")) match {
    case Success(person) => println(person.surname)
    case Failure(ex) => // Handle error ...
}

Zarówno

Różne typy danych dla błędu / sukcesu

def getPersonFromWebService(url: String): Either[String, Person] = {
    
    val response = webServiceClient.get(url)

    response.webService.status match {
        case 200 => {
            val person = parsePerson(response)
            if(!isValid(person)) Left("Validation failed")
            else Right(person)
        }

        case _ => Left(s"Request failed with error code $response.status")
    }
}

Dopasowywanie wzorca dla dowolnej wartości

getPersonFromWebService("http://some-webservice.com/person") match {
    case Left(errorMessage) => println(errorMessage)
    case Right(person) => println(person.surname)
}

Konwertuj dowolną wartość na opcję

val maybePerson: Option[Person] = getPersonFromWebService("http://some-webservice.com/person").right.toOption

Opcja

Używanie wartości null jest zdecydowanie odradzane, chyba że interakcja ze starszym kodem Java, który oczekuje null . Zamiast Option powinna być stosowana, gdy wynik funkcji może być albo coś ( Some ) albo nic ( None ).

Blok try-catch jest bardziej odpowiedni do obsługi błędów, ale jeśli funkcja może nic nie zwracać, Option jest odpowiednia i prosta.

Option[T] może być Some(value) (zawiera wartość typu T ) lub None :

def findPerson(name: String): Option[Person]

Jeśli nie zostanie znaleziona żadna osoba, None można zwrócić. W przeciwnym razie zwracany jest obiekt typu Some zawierający obiekt Person . Poniżej przedstawiono sposoby obsługi obiektu typu Option .

Dopasowywanie wzorów

findPerson(personName) match {
    case Some(person) => println(person.surname)
    case None => println(s"No person found with name $personName")
}

Korzystanie z mapy i getOrElse

val name = findPerson(personName).map(_.firstName).getOrElse("Unknown")
println(name) // Prints either the name of the found person or "Unknown"

Używanie krotnie

val name = findPerson(personName).fold("Unknown")(_.firstName)
// equivalent to the map getOrElse example above.

Konwertowanie na Javę

Jeśli chcesz przekonwertować typ Option na zerowy typ Java dla interoperacyjności:

val s: Option[String] = Option("hello")
s.orNull           // "hello": String
s.getOrElse(null)  // "hello": String

val n: Option[Int] = Option(42)
n.orNull           // compilation failure (Cannot prove that Null <:< Int.)
n.getOrElse(null)  // 42

Obsługa błędów pochodzących z kontraktów futures

Kiedy exception zostanie zgłoszony w Future , możesz (powinieneś) użyć recover aby go obsłużyć.

Na przykład,

def runFuture: Future = Future { throw new FairlyStupidException }

val itWillBeAwesome: Future = runFuture

... rzuci Exception z Future . Ale widząc, jak możemy przewidzieć, że Exception typu FairlyStupidException z dużym prawdopodobieństwem, możemy konkretnie obsłużyć tę sprawę w elegancki sposób:

val itWillBeAwesomeOrIllRecover = runFuture recover { 
    case stupid: FairlyStupidException => 
         BadRequest("Another stupid exception!") 
}

Jak widać metoda podana w celu recover to PartialFunction nad domeną wszystkich Throwable , więc możesz obsłużyć tylko kilka typów, a następnie pozwolić reszcie przejść do eteru obsługi wyjątków na wyższych poziomach w stosie Future .

Zauważ, że jest to podobne do uruchamiania następującego kodu w kontekście innym niż Future :

def runNotFuture: Unit = throw new FairlyStupidException

try {
    runNotFuture
} catch {
    case e: FairlyStupidException => BadRequest("Another stupid exception!")
}

Naprawdę ważne jest zajmowanie się wyjątkami generowanymi w Future s, ponieważ przez większość czasu są bardziej podstępni. Zwykle nie dostają wszystkiego w twarz, ponieważ działają w innym kontekście wykonywania i wątku, a zatem nie monitują o ich naprawę, gdy się zdarzają, szczególnie jeśli nie zauważysz niczego w dziennikach lub zachowaniu podanie.

Korzystanie z klauzul try-catch

Oprócz funkcjonalnych konstrukcji, takich jak Try , Option i Either do obsługi błędów, Scala obsługuje również składnię podobną do Javy, używając klauzuli try-catch (z potencjalnym blokiem w końcu). Klauzula catch jest dopasowaniem wzorca:

try { 
  // ... might throw exception
} catch {
  case ioe: IOException => ... // more specific cases first
  case e: Exception => ...
  // uncaught types will be thrown
} finally {
  // ...
}

Konwertuj wyjątki na jeden lub na typ opcji

Aby przekonwertować wyjątki na typy Either lub Option , można użyć metod podanych w scala.util.control.Exception

import scala.util.control.Exception._

val plain = "71a"
val optionInt: Option[Int] = catching(classOf[java.lang.NumberFormatException]) opt { plain.toInt }
val eitherInt = Either[Throwable, Int] = catching(classOf[java.lang.NumberFormatException]) either { plain.toInt }


Modified text is an extract of the original Stack Overflow Documentation
Licencjonowany na podstawie CC BY-SA 3.0
Nie związany z Stack Overflow