La soluzione è quella di utilizzare Option.map
e Option.flatMap
:
First.flatMap(_.second.flatMap(_.third.map(_.numberOfSmth)))
O l'equivalente (vedere la aggiornamento alla fine di questa risposta):
First flatMap(_.second) flatMap(_.third) map(_.numberOfSmth)
Ciò restituisce un Option[Int]
(fornito che numberOfSmth
restituisce un Int
). Se una delle opzioni nella catena di chiamate è None
, il risultato sarà None
, altrimenti sarà Some(count)
dove count
è il valore restituito da numberOfSmth
.
Ovviamente questo può diventare brutto molto velocemente. Per questo motivo scala supporta per le comprensibili come zucchero sintattico.Quanto sopra può essere riscritta come:
for {
first <- First
second <- first .second
third <- second.third
} third.numberOfSmth
che è probabilmente più bello (soprattutto se non siete ancora abituati a vedere map
/flatMap
ovunque, come sarà certamente il caso dopo un po 'utilizzando Scala), e genera l'esatto stesso codice sotto il cofano.
per più di fondo, si può controllare questo altro problema: What is Scala's yield?
UPDATE: Grazie a Ben James per aver ricordato che flatMap è associativa. In altre parole, x flatMap(y flatMap z)))
corrisponde a x flatMap y flatMap z
. Mentre quest'ultimo di solito non è più breve, ha il vantaggio di evitare qualsiasi nidificazione, che è più facile da seguire.
Ecco alcune illustrazione nel REPL (i 4 stili sono equivalenti, con i primi due con flatMap nidificazione, le altre due con catene piane di flatMap):
scala> val l = Some(1,Some(2,Some(3,"aze")))
l: Some[(Int, Some[(Int, Some[(Int, String)])])] = Some((1,Some((2,Some((3,aze))))))
scala> l.flatMap(_._2.flatMap(_._2.map(_._2)))
res22: Option[String] = Some(aze)
scala> l flatMap(_._2 flatMap(_._2 map(_._2)))
res23: Option[String] = Some(aze)
scala> l flatMap(_._2) flatMap(_._2) map(_._2)
res24: Option[String] = Some(aze)
scala> l.flatMap(_._2).flatMap(_._2).map(_._2)
res25: Option[String] = Some(aze)
Solo una nota, ma il woun flatMap' t lavorare come indicato di seguito più volte. Dovrebbe essere 'First.second.flatMap (_. Third.flatMap (_. NumberOfSmth)). Get' ed è ancora possibile generare ed eccezione – korefn
Infatti, grazie. Grazie a tutti per le vostre risposte, ho trovato quello che stavo cercando. – psisoyev