2016-07-01 10 views
0

간단한 케이스 (2 개 선물)에서 작동하는 코드가 있지만 무제한 선물을 위해 일반화하는 방법을 찾을 수 없습니다.스칼라에서 조건부 선물의 구성

미래를 부르는 코드를 만들고, 미래가 완료되면 다른 코드를 호출하고,이 코드가 완료되면 다른 코드를 호출하는 등의 작업을하고 싶습니다.

전화를 다시 걸 필요가 없기 때문에 다음 호출을하기 전에 각 호출의 결과가 필요합니다 (이것은 나의 정지 조건 임).

나는 이것이 재귀를 통해 명시 적으로 해결 될 수 있음을 알고 있지만 가능한 모든 경우 이해 및/또는 폴드를 사용하는 솔루션을 원합니다. 나는 그런 해결책이 있어야한다고 느낀다. 그러나 나는 그것을 정확하게 쓸 수 없다. 여기

내가 무한히 많은 그런 미래를 작성하고 마지막에 (목록의 하나의 미래를) 모두에 가입하고자하는

두 개의 임의의 int

이제
def nextValue: Future[List[Int]] = Future{ 
    Thread.sleep(1000) 
    val num1 = Random.nextInt(10) 
    val num2 = Random.nextInt(10) 
    List(num1,num2) 
} 

의 AA 목록을 생성 AA 기능입니다

난 그냥 테스트 목적으로

이 2리터 작동을 위해 await.result 전화 드렸습니다 N 개의 호출에 대해 일반화하는 방법은 무엇입니까?

Await.result({ 
    nextValue.flatMap{ value1 => 
    nextValue.map{ value2 => 
     value1 ++ value2 
    } 
    } 
},1.minute) 
+0

각'Future'가 이전에 완료된 후에 만 ​​시작될 경우,'Future'를 사용하는 것은 무엇입니까? 멈춤 조건이 충족되었을 때 완료 할 단일'Future'에서'fold '또는'Stream'을 래핑 할 수 있습니까? – jwvh

답변

1
Future.sequence((0 to 100).map(_ => nextValue)).map(_.flatten) 

사용법 : here에서

//import scalaz._,Scalaz._ 
// --or-- 
//import cats.syntax.traverse._ 
//import cats.std.list._ 
//import cats.std.future._ 

(0 to 100).toList.traverseM(_ => nextValue) 

Eplanation :

scala> Future.sequence((0 to 100).map(_ => nextValue)).map(_.flatten) 
res3: scala.concurrent.Future[scala.collection.immutable.IndexedSeq[Int]] = [email protected] 

scala> Await.result(res3, duration.Duration.Inf) 
res4: scala.collection.immutable.IndexedSeq[Int] = Vector(5, 4, 3, 0, 4, 6, 0, 8, 0, 0, 4, 6, 2, 7, 4, 9, 8, 8, 6, 9, 1, 4, 5, 5, 8, 2, 2, 7, 6, 0, 5, 6, 6, 5, 9, 6, 3, 5, 7, 1, 3, 2, 5, 3, 3, 1, 8, 4, 6, 7, 5, 1, 3, 5, 7, 4, 1, 5, 9, 4, 5, 0, 1, 8, 5, 0, 0, 7, 4, 2, 4, 2, 2, 0, 4, 1, 6, 3, 8, 2, 1, 3, 5, 5, 8, 3, 6, 1, 3, 2, 9, 4, 9, 4, 7, 5, 7, 8, 7, 9, 5, 2, 5, 0, 2, 5, 6, 8, 6, 2, 3, 2, 0, 8, 9, 3, 9, 2, 7, 5, 1, 7, 1, 1, 8, 6, 8, 0, 5, 5, 6, 0, 8, 8, 3, 6, 4, 2, 7, 1, 0, 3, 3, 3, 3, 2, 8, 7, 3, 3, 5, 1, 6, 3, 3, 7, 8, 9, 9, 9, 1, 9, 9, 8, 1, 1, 5, 8, 1, 1, 7, 6, 3, 2, 5, 0, 4, 3, 0, 9, 9, 1, 2, 0, 3, 6, 2, 6, 8, 6, 6, 3, 9, 7, 1, 3, 5, 9, 6, 5, 6, 2) 

또는 scalaz/고양이

traverseM가 (F) equival입니다 (f) .map (_. join)을 트래버스합니다. 여기서 join은 입니다. flatten의 scalaz 이름입니다.

import fs2._ 
import fs2.util._ 

def nextValue: Task[List[Int]] = Task.delay{ 
    import scala.util.Random 
    val num1 = Random.nextInt(10) 
    val num2 = Random.nextInt(10) 
    if(num1 > 5) List(num1,num2) else List() 
} 
Stream.repeatEval(nextValue).takeWhile(_.size > 0).runLog.map(_.flatten).unsafeRun 

https://github.com/functional-streams-for-scala/fs2/blob/series/0.9/docs/guide.md

: 당신은 몇 가지 조건을 원하고 여전히 비동기를 유지해야하는 경우


, 당신은 FS2 사용할 수 있습니다 : 그것은 " flatMap 해제"의 일종으로 유용 Iteratees에서도 마찬가지입니다.

고양이 : https://github.com/travisbrown/iteratee,691,363,210 또는 scalaz-iteratee 패키지

일반적으로 모나드/ApplicativeFunctor을 통해 일반화 할 수없는 표준 라이브러리의 Stream (같은 실제로 unfold이고 같은 스칼라에서 펼쳐에 대한 좋은 지원이 없기 때문에, 당신은 fold 이것을 구현할 수 없습니다 말하기 EnumeratorT) - 전개 단계마다 Await.result을 수행하면 조건을 점검 할 수 있습니다.

+0

OP가 종료 조건에 따라 결정된 길이의 컬렉션을 찾고 있다고 생각했습니다. 즉, 종단 결과를 얻을 때까지 'nextValue'를 가져옵니다. – jwvh

+0

당신 말이 맞아, 나는 조심스럽게 질문을 읽지 않았다 - 내 대답 – dk14

+0

예 ... 업데이 트됩니다 getNext의 결과가 유효한지 확인하고 그렇지 않으면 종료하고 싶습니다. 이것이 가능한가? –

관련 문제