条件为

时间:2017-06-02 04:13:17

标签: scala functional-programming applicative scala-cats

您好我有cats

的以下Scala代码
results = patrons.map(p => {
  (verifyCardId(p.cardId), verifyAddress(p.address)).map2(
  (maybeValidCard, maybeValidAddress) => {
    val result = for {
      idCheck <- maybeValidCard
      addressCheck <- maybeValidAddress
    } yield CheckResult(p.name, idCheck, addressCheck)
  }
})

其中verifyCardIdverifyAddress是一个外部API调用,返回Future,这在某种程度上非常昂贵且耗时。

问题是如何执行以下操作:

  • 如果其中一位顾客没有卡,代码应该可以跳过检查卡仍然必须检查顾客的地址
  • 如果赞助人同时拥有,则代码应检查卡和地址

如何改进现有代码?谢谢堆

编辑: 添加有关首选项的更多信息,以跳过一个昂贵的API调用

1 个答案:

答案 0 :(得分:0)

  • 如果地址验证结果不依赖于卡片验证结果,则解开它们(flatMap绑定monad)。
  • 模型CheckResult应调整为丢失卡片的情况。

扩展样本

    case class Patron(name: String, cardId: String, address: String)
    case class CheckResult(name: String, idCheck: Option[Boolean], addressCheck: Boolean)
    def verifyCardId(cardId: String) = Future{
      Thread.sleep(5000)
      Some(true)
    }
    def verifyAddress(address: String) = Future{
      Thread.sleep(5000)
      Some(true)
    }

    val patrons = List(Patron("p_name", "1234", "Somewhere St. 42"))

    val start = LocalDateTime.now()
    val results = patrons.map(p => {
      (verifyCardId(p.cardId), verifyAddress(p.address)).map2(
        (maybeValidCard, maybeValidAddress) => {
          for {
            addressCheck <- maybeValidAddress
          } yield CheckResult(p.name, maybeValidCard, addressCheck)
        })
    })
    val headResult = Await.result(results.head, Duration.Inf)
    val end = LocalDateTime.now()
    val duration = ChronoUnit.SECONDS.between(start, end)

短输出

    patrons: List[Patron] = List(Patron(p_name,1234,Somewhere St. 42))
    headResult: Option[CheckResult] = Some(CheckResult(p_name,Some(true),true))
    duration: Long = 5