2015-03-19 83 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() } 
    } 
    } 

}