2015-03-19 33 views
0

我想弄清楚如何以遞歸方式使用Scala期貨。我使用的用例是將一個資源(ResourceOne)的輸出與另一個資源(ResourceTwo)輸出進行比較,如果它們之間存在任何差異,我想同步第一個資源(ResourceOne)並再次檢索資源我從resourceOne檢索的項目數與resourceTwo同步。但是,由於我的操作(檢索和刪除)與ResourceOne返回未來,我堅持我的邏輯中途。下面是一個例子說明我的問題,關於完成步驟#3和#4以及爲步驟#5遞歸#1到#4遞歸的任何想法?Scala:遞歸使用未來

package com.example 

import scala.concurrent.Future 
import scala.collection.mutable.Map 
import scala.concurrent.ExecutionContext.Implicits.global 

object ResourceOne { 

    //var resources = List("one", "two","three","four","five","six","seven","eight","nine") 
    var resources = List("one", "two","three") 

    def getFirstFive():Future[List[String]] = Future { 
    resources.take(5) 
    } 

    def remove(res:String) = Future { 
    println(s"Deleting ${res}") 
    resources = resources.filter(! _.equals(res)) 
    } 
} 

object ResourceTwo { 

    val resourceDetails = Map("one" ->"oneDetail", "three" -> "threeDetail","four" ->"fourDetails","six" -> "sixDetail", "eight" -> "eightDetail") 

    def getResourceDetail(resource:String) = { 
    resourceDetails.get(resource); 
    } 
} 

object HelloFuture { 

    def main(args: Array[String]): Unit = { 

    println("1. Fetching first five") 
    val resF = ResourceOne.getFirstFive() 

    println("2. Retrieving the resource detail from ResourceTwo, if a resourceDetail does not exist then delete the resource from resourceOne") 
    val resFOut = resF.map(resList => { 
     resList.map(resOne => { 
      val resOneDetail = ResourceTwo.getResourceDetail(resOne) 
      //println(s"Resource details for ${resOne} is ${resOneDetail}") 
      if(resOneDetail == None) { 
       println("2.a delete resource if detail is not available") 
       ResourceOne.remove(resOne) 
      } 
      }) 
     }) 

    println("3. Verifying if all the resources retrieved from resourceOne were available in resourceTwo or not.") 
    //TODO 

    println("4. If all were not available then retrieve from resourceOne again as the missing ones will have been deleted.") 
    //TODO 

    println("5. Repeat step 1 thru 4 till all resources retreived from resourceOne are available in resourceTwo.")  

    } 
} 

回答

0

環顧四周,想出了下面的解決方案。雖然ResourceOne.remove()有一個小問題,但ResourceOne.remove()返回未來,而下面的實現不能很好地處理它,並導致fetchResource()運行幾次,直到完成ResourcesOne.remove()。不知道如何處理。

package com.example 

import scala.concurrent.Future 
import scala.util.{Success,Failure} 
import scala.collection.mutable.Map 
import scala.concurrent.ExecutionContext.Implicits.global 

object ResourceOne { 

    //var resources = List("one", "two","three","four","five","six","seven","eight","nine") 
    var resources = List("one", "two","three") 

    def getFirstFive():Future[List[String]] = Future { 
    resources.take(5) 
    } 

    def remove(res:String) = Future { 
    println(s"Deleting ${res}") 
    resources = resources.filter(! _.equals(res)) 
    } 
} 

object ResourceTwo { 

    val resourceDetails = Map("one" ->"oneDetail", "three" -> "threeDetail","four" ->"fourDetails","six" -> "sixDetail", "eight" -> "eightDetail") 

    def getResourceDetail(resource:String) = { 
    resourceDetails.get(resource); 
    } 
} 

object HelloFuture { 

    def main(args: Array[String]): Unit = { 

    val fOut = fetchResource() 
    fOut.map{ detail => println("Final Detail retreived is "+ detail) } 

    } 

    // Gets from resourceOne and if the detail is not found in resourceTwo then deletes from resourceOne and refetches from resourceOne till both the fetches match 
    def fetchResource():Future[List[Any]] = { 
    println("Fetching first five") 
    val resF = ResourceOne.getFirstFive() 

    var resOneCount = 0; 
    val resFOut = resF.map(resList => { 
     resList.map(resOne => { 
      val resOneDetail = ResourceTwo.getResourceDetail(resOne) 
      resOneCount += 1 
      resOneDetail match { 
       case Some(_) => { resOneDetail } 
       case None => { ResourceOne.remove(resOne) ; resOneDetail } 
      } 
      }) 
     }) 

    resFOut flatMap { 
     case x if x.filter(_ != None).size == resOneCount => Future.successful(x) 
     case _ => { fetchResource() } 
    } 
    } 

}