How do you stop building an Option[Collection] upon reaching the first None?

前端 未结 5 1323
夕颜
夕颜 2020-12-18 03:52

When building up a collection inside an Option, each attempt to make the next member of the collection might fail, making the collection as a whole a failure, t

5条回答
  •  鱼传尺愫
    2020-12-18 04:41

    Scala collections have some options to use laziness to achieve that.

    You can use view and takeWhile:

    def allPartsWithView(names: Seq[String]): Option[Seq[Part]] = {
        val successes = names.view.map(findPartByName)
                                  .takeWhile(!_.isEmpty)
                                  .map(_.get)
                                  .force
        if (!names.isDefinedAt(successes.size)) Some(successes)
        else None
    }
    

    Using ifDefinedAt avoids potentially traversing a long input names in the case of an early failure.

    You could also use toStream and span to achieve the same thing:

    def allPartsWithStream(names: Seq[String]): Option[Seq[Part]] = {
        val (good, bad) = names.toStream.map(findPartByName)
                                        .span(!_.isEmpty)
        if (bad.isEmpty) Some(good.map(_.get).toList)
        else None
    }
    

    I've found trying to mix view and span causes findPartByName to be evaluated twice per item in case of success.

    The whole idea of returning an error condition if any error occurs does, however, sound more like a job ("the" job?) for throwing and catching exceptions. I suppose it depends on the context in your program.

提交回复
热议问题