2017-06-02 114 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