Como você para de construir uma Opção [Coleção] ao alcançar a primeira Nenhuma?
Ao criar uma coleção dentro de umOption
, cada tentativa de tornar o próximo membro da coleção pode falhar, tornando a coleção como um todo uma falha também. Após a primeira falha em fazer um membro, eu gostaria de desistir imediatamente e retornarNone
para toda a coleção. Qual é a maneira idiomática de fazer isso no Scala?
Aqui está uma abordagem que eu propus:
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
}
}
Em outras palavras, se houver uma chamada parafindPartByName
retornaNone
, allParts
retornaNone
. De outra forma,allParts
retorna umSome
contendo uma coleção deParts
, todos com garantia de validade. Uma coleção vazia está OK.
O acima tem a vantagem de parar de chamarfindPartByName
após a primeira falha. Mas ofoldLeft
ainda itera uma vez para cada nome, independentemente.
Aqui está uma versão que se destaca assim quefindPartByName
retorna umNone
:
def allParts2(names: Seq[String]): Option[Seq[Part]] = Some(
for (name <- names) yield findPartByName(name) match {
case Some(part) => part
case None => return None
}
)
Atualmente, acho a segunda versão mais legível, mas (a) o que parece mais legível provavelmente mudará à medida que tiver mais experiência com o Scala, (b) tenho a impressão de que cedoreturn
é desaprovado em Scala, e (c) nenhum parece tornar o que está acontecendo especialmente óbvio para mim.
A combinação de "tudo ou nada" e "desistir da primeira falha" parece um conceito de programação tão básico, eu acho que deve haver um Scala comum ou um idioma funcional para expressá-lo.