2017-06-02 79 views
1

嗨,我有以下Scala代码与cats斯卡拉MapN与条件

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调用之一

回答

0
  • 如果地址验证的结果不依赖于卡验证的结果,那么解开它们(flatMap结合单子)。
  • 模型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 
+0

感谢您的回答,但我想我没有解释我的意图不够好。我已经更新了这个问题。诚然,这两个验证不依赖于对方。但如果两者都可以同时调用以节省时间,则也是首选。我的意图是跳过其中的一个特定场景(即没有卡) –

+0

我更新了答案。只有通话结果已解开。期货是以异步方式并行计算的。 – Zernike