Как вы перестаете строить Option [Collection] после достижения первого None?

При создании коллекции внутриOptionкаждая попытка сделать следующий элемент коллекции может потерпеть неудачу, что также приведет к сбою всей коллекции. После первого отказа сделать член, я хотел бы немедленно сдаться и вернутьсяNone для всей коллекции. Какой идиоматический способ сделать это в Scala?

Вот один из подходов, который я предложил:

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
    }
  }

Другими словами, если любой вызовfindPartByName возвращаетсяNone, allParts возвращаетсяNone, Иначе,allParts возвращаетSome содержащий коллекциюParts, все из которых гарантированно действительны. Пустая коллекция в порядке.

Вышеуказанное имеет то преимущество, что перестает звонитьfindPartByName после первой неудачи. НоfoldLeft по-прежнему повторяется один раз для каждого имени, независимо.

Вот версия, которая выручает, как только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
  }
)

В настоящее время я нахожу вторую версию более читабельной, но (а) то, что кажется наиболее читабельным, вероятно, изменится, когда я получу больше опыта со Scala, (б) у меня сложилось впечатление, что раноreturn не одобряется в Scala, и (c) ни один из них, кажется, не делает происходящее особенно очевидным для меня.

Комбинация «все или ничего» и «отказаться от первого отказа» кажется такой базовой концепцией программирования, я полагаю, что для ее выражения должна быть общая Scala или функциональная идиома.

Ответы на вопрос(5)

Ваш ответ на вопрос