Scala - 按顺序评估函数调用,直到返回一次

Joh*_*nny 7 scala

我有一些"遗留"端点可以返回我正在寻找的数据.

def mainCall(id): Data {

    maybeMyDataInEndpoint1(id: UUID): DataA

    maybeMyDataInEndpoint2(id: UUID): DataB

    maybeMyDataInEndpoint3(id: UUID): DataC
}
Run Code Online (Sandbox Code Playgroud)
  • null如果DataX找不到,可以退回
  • 每种方法的返回类型都不同.有一种convert方法可以将每个转换DataX为统一Data.
  • 端点不是Scala-ish

什么是最好的Scala方法来顺序评估这些方法调用,直到我有我需要的值?

在伪我会做类似的事情:

val myData = maybeMyDataInEndpoint1 getOrElse maybeMyDataInEndpoint2 getOrElse maybeMyDataInEndpoint3
Run Code Online (Sandbox Code Playgroud)

Oss*_*sip 17

我会使用更简单的方法,但其他答案使用更精细的语言功能.只是Option()用来捕捉null链条orElse.我正在假设convertX(d:DataX):Data显式转换的方法.因为它可能根本找不到我们返回Option

def mainCall(id: UUID): Option[Data] {
  Option(maybeMyDataInEndpoint1(id)).map(convertA)
  .orElse(Option(maybeMyDataInEndpoint2(id)).map(convertB))
  .orElse(Option(maybeMyDataInEndpoint3(id)).map(convertC))
}
Run Code Online (Sandbox Code Playgroud)


che*_*ohi 5

也许你可以将这些方法作为Lists的高阶函数来解除collectFirst,例如:

  val fs = List(maybeMyDataInEndpoint1 _, maybeMyDataInEndpoint2 _, maybeMyDataInEndpoint3 _)

  val f = (a: UUID) => fs.collectFirst {
    case u  if u(a) != null => u(a)
  }
  r(myUUID)
Run Code Online (Sandbox Code Playgroud)


g.k*_*tev 5

最好的办法斯卡拉恕我直言,是做事情的最直接方法.

  • 要处理可选值(或null来自Java land),请使用Option.
  • 要按顺序评估方法列表,请折叠Seq一系列函数.
  • 要从一种数据类型转换为另一种数据类型,请根据情况和您的偏好使用(1.)隐式转换或(2.)常规函数.

    1. (编辑)假设隐式转换:

      def legacyEndpoint[A](endpoint: UUID => A)(implicit convert: A => Data) =
        (id: UUID) => Option(endpoint(id)).map(convert)
      
      val legacyEndpoints = Seq(
        legacyEndpoint(maybeMyDataInEndpoint1),
        legacyEndpoint(maybeMyDataInEndpoint2),
        legacyEndpoint(maybeMyDataInEndpoint3)
      )
      
      def mainCall(id: UUID): Option[Data] =
        legacyEndpoints.foldLeft(Option.empty[Data])(_ orElse _(id))
      
      Run Code Online (Sandbox Code Playgroud)
    2. (编辑)使用显式转换:

      def legacyEndpoint[A](endpoint: UUID => A)(convert: A => Data) =
        (id: UUID) => Option(endpoint(id)).map(convert)
      
      val legacyEndpoints = Seq(
        legacyEndpoint(maybeMyDataInEndpoint1)(fromDataA),
        legacyEndpoint(maybeMyDataInEndpoint2)(fromDataB),
        legacyEndpoint(maybeMyDataInEndpoint3)(fromDataC)
      )
      
      ... // same as before
      
      Run Code Online (Sandbox Code Playgroud)