Решение заключается в использовании Option.map
и Option.flatMap
:
First.flatMap(_.second.flatMap(_.third.map(_.numberOfSmth)))
или эквивалент (см обновление в конце этого ответа):
First flatMap(_.second) flatMap(_.third) map(_.numberOfSmth)
Это возвращает Option[Int]
(при условии, что numberOfSmth
возвращает Int
). Если какой-либо из вариантов в цепочке вызовов равен None
, результатом будет None
, в противном случае это будет Some(count)
, где count
- это значение, возвращаемое numberOfSmth
.
Конечно, это может стать уродливым очень быстро. По этой причине scala поддерживает для понимания как синтаксический сахар.Выше можно переписать в виде:
for {
first <- First
second <- first .second
third <- second.third
} third.numberOfSmth
Который, возможно, лучше (особенно, если вы еще не привыкли видеть map
/flatMap
везде, так как, безусловно, будет иметь место через некоторое время с помощью Scala) и генерирует точный тот же код под капотом.
Для более фона, вы можете проверить это другой вопрос: What is Scala's yield?
UPDATE: Благодаря Бен Джеймс за указание на то, что flatMap ассоциативно. Другими словами x flatMap(y flatMap z)))
- это то же самое, что и x flatMap y flatMap z
. Хотя последнее, как правило, не короче, оно имеет преимущество в том, чтобы избежать какой-либо гнездования, что легче выполнить.
Вот некоторые иллюстрации в REPL (на 4 типа эквивалентны, с первых два используя flatMap вложенности, другие две с использованием плоских цепей 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)
Просто к сведению, но в Woun flatMap» t, как указано ниже несколько раз. Это должно быть 'First.second.flatMap (_. Third.flatMap (_. NumberOfSmth)). Get' и все еще может выбрасывать и исключать – korefn
Действительно, спасибо. Спасибо всем за ваши ответы, я нашел то, что искал. – psisoyev