First flatMap(_.second) flatMap(_.third) map(_.numberOfSmth)
ta zwraca Option[Int]
(pod warunkiem że numberOfSmth
zwraca Int
). Jeśli którakolwiek z opcji w łańcuchu wywołań to None
, wynikiem będzie None
, w przeciwnym razie będzie to Some(count)
, gdzie count
jest wartością zwróconą przez numberOfSmth
.
Oczywiście może to być bardzo brzydkie. Z tego powodu scala obsługuje dla pojmowania jako cukru syntaktycznego.Powyższe może być zapisane jako:
for {
first <- First
second <- first .second
third <- second.third
} third.numberOfSmth
Który jest prawdopodobnie ładniejsze (zwłaszcza jeśli nie są jeszcze przyzwyczajeni do map
/flatMap
wszędzie, a na pewno będzie miało miejsce po jakimś czasie, używając Scala) i generuje dokładne ten sam kod pod maską.
Więcej tle, można sprawdzić to inne pytanie: What is Scala's yield?
UPDATE: Dzięki Ben James za wskazanie, że flatMap jest łączne. Innymi słowy, x flatMap(y flatMap z)))
jest taki sam jak x flatMap y flatMap z
. Podczas gdy ta ostatnia zazwyczaj nie jest krótsza, ma tę zaletę, że unika zagnieżdżania się, co jest łatwiejsze do naśladowania.
Oto ilustracja w REPL (z 4 stylów są równoważne, przy czym dwa pierwsze używając flatMap gniazdowania, dwa pozostałe za pomocą płaskich łańcuchów 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)
Tylko uwaga ale woun flatMap” t działają tak, jak podano poniżej kilka razy. Powinien to być 'First.second.flatMap (_. Third.flatMap (_. NumberOfSmth)). Get' i nadal może rzutować i być może wyjątek – korefn
Rzeczywiście, dziękuję. Dziękuję wszystkim za odpowiedzi, znalazłem to, czego szukałem. – psisoyev