内でコレクションを構築する場合、コレクションOption
の次のメンバーを作成しようとするたびに失敗し、コレクション全体も失敗する可能性があります。None
メンバーを作るのに最初に失敗したら、すぐにあきらめて、コレクション全体に戻りたいと思います。Scalaでこれを行う慣用的な方法は何ですか?
これが私が思いついた1つのアプローチです:
def findPartByName(name: String): Option[Part] = . . .
def allParts(names: Seq[String]): Option[Seq[Part]] =
names.foldLeft(Some(Seq.empty): Option[Seq[Part]]) {
(result, name) => result match {
case Some(parts) =>
findPartByName(name) flatMap { part => Some(parts :+ part) }
case None => None
}
}
つまり、 return を呼び出すと、 return がfindPartByName
返されます。それ以外の場合は、すべてが有効であることが保証されているのコレクションを含む を返します。空のコレクションは問題ありません。None
allParts
None
allParts
Some
Parts
上記にはfindPartByName
、最初の失敗の後に呼び出しを停止するという利点があります。ただしfoldLeft
、関係なく、名前ごとに 1 回繰り返します。
findPartByName
を返すとすぐに救済するバージョンは次のNone
とおりです。
def allParts2(names: Seq[String]): Option[Seq[Part]] = Some(
for (name <- names) yield findPartByName(name) match {
case Some(part) => part
case None => return None
}
)
私は現在、2 番目のバージョンの方が読みやすいと感じていますが、(a) 最も読みやすいと思われるものは、Scala の経験を積むにつれて変わる可能性が高く、(b) Scala では早期return
は嫌われているという印象を受けます。(c) どちらもありません。何が起こっているのかを特に明白にしているようです。
「オール オア ナッシング」と「最初の失敗であきらめる」の組み合わせは、基本的なプログラミング概念のように思えます。それを表現するには、一般的な Scala または関数型イディオムが必要だと思います。