如果尝试失败,短路图操作

问题描述 投票:0回答:2

我有这样的功能:

def foo(item: Item) : Option[Int] = Try{
  // Some code that can blow up
}.toOption

我有一个项目列表,我想通过它们进行映射,并应用上述功能。但是,如果上面的函数崩溃并返回None,则映射结果应该是错误的:

items.map{
  item => foo(item)
}

在这里做地图不正确吗?看起来不像]

scala short-circuiting
2个回答
2
投票

这称为traverse。如果可以使用cats,则非常简单:

import cats.implicits._

val result = items.traverse(foo) // Option[List[Int]]

如果没有,您可以很容易地实现它:

def traverse[A, B](data: List[A])(f: A => Option[B]): Option[List[B]] = {
  @annotation.tailrec
  def loop(remaining: List[A], acc: List[B]): Option[List[B]] =
    remaining match {
      case a :: as => f(a) match {
        case Some(b) => loop(remaining = as, b :: acc)
        case None => None
      }

      case Nil => Some(acc.reverse)
    }

  loop(remaining = data, acc = List.empty)
}

您可以这样使用:

val result = traverse(items)(foo) // Option[List[Int]]

(但是,我建议您使用cats,因为它更通用)


2
投票

对于开箱即用的短路,请考虑像这样用Try包装列表映射

def fooUnsafe(item: Item): Int = // might throw
Try(items.map(fooUnsafe))

如果您希望保留def foo(item: Item) : Option[Int]签名,则以下内容也会短路

Try(list.map(v => foo(v).get))
© www.soinside.com 2019 - 2024. All rights reserved.