2013-04-15 1 views
1

이것은 문체적인 질문과 나의 스칼라 이해를 넓히려 고 시도한 것의 조합입니다.시도 할 수 없습니다. 이해를 시도하십시오

import scala.util.Try 
import scala.concurrent._ 
import ExecutionContext.Implicits.global 

val l= List(Future.successful(1),Future.failed(new IllegalArgumentException)) 

implicit def try2Traversible[A](xo: Try[A]): Iterable[A] = xo.toOption.toList 

val res = for{f <- l; v <- f.value} yield v 

scala> res: List[scala.util.Try[Int]] = List(Success(1), Failure(java.lang.IllegalArgumentException)) 

res.flatten 
res16: List[Int] = List(1) 

는 내가하고 싶은 것은 얻을 수 있습니다 :

나는 미래의가, 나, 선물의 값을 계산 옵션의로 변환하고,이 이해를 위해 사용하여 목록을 평평하게 할 포함 된 목록을 가지고있다 이해하기 쉬운 무대로, 어떤 제안이있어?

답변

1

생각은 for-comprehension 자체 내에서 Option (즉, 0 또는 1 요소 컬렉션) 인 것처럼 Try 개체로 이동하는 것입니다. 이 트래 버설을 사용하려면 Try 유형에서 Option 유형으로 변환해야합니다.

이 작동합니다 :

implicit def try2option[A](xo: Try[A]) = xo.toOption 

val res = for (f <- l; t <- f.value; x <- t) yield x 
2

이렇게이 올바르지 않습니다

for{f <- l; v <- f.value} yield v 
선물이 이미 value 멤버가 정의 된 이유입니다, fulfiled 만 있기 때문에 귀하의 경우 작업 표시

. 그러나 일반적인 경우에는 이해를 실행하면 아직 채워지지 않을 수도 있으므로 valueNone 을 반환 할 것입니다. 사실 언젠가는 실현 될 예정 임에도 불구하고 말입니다. 예를함으로써, REPL이 시도 : l에서 미래의 어느 것도 아직 충족되지 않기 때문에

val f1 = Future{ 
    Thread.sleep(3000) // Just a test to illustrate, never do this! 
    1 
} 
val f2 = Future{ 
    Thread.sleep(3000) // Just a test to illustrate, never do this! 
    throw new IllegalArgumentException 
} 

val l = List(f1, f2) 
for{f <- l; v <- f.value} yield v 

결과는 빈 목록입니다. 그런 다음 잠깐 (최대 3 초) 기다린 후 이해력 (마지막 줄)을 다시 실행하면 선물이 최종적으로 충족되었으므로 비어 있지 않은 목록이 표시됩니다.

는이 문제를 해결하려면, 당신은 (즉 fulfiled 할 수있는 모든 선물을 기다리는) 중 블록에있을 것이다 scala.concurrent.Await를 사용하거나 Future.map 또는 Future.flatMap 같은 것을 사용하여 비동기 세계에 머물. 차단하려는 경우 예를함으로써, 당신은 할 수 :

Await.result(Future.sequence(l), duration.Duration.Inf) 

Await.result 대기 미래의 결과를, 동기 세계에 비동기 세계에서 갈 수 있도록. 위의 결과는 List[Int] 입니다. 문제는 이제 실패 사례를 잃게되고 (결과는 List[Try[Int]]이 아니므로) 실제로 첫 번째 예외를 다시 제기합니다. 당신이 할 수있는, 그것을 사용 https://stackoverflow.com/a/15776974/1632462 : 는이 문제를 해결하려면, 당신은 내가 다른 대답에 게시이 도우미 메서드를 사용할 수있는 모든 선물이 올바른 값 중 하나 (fulfiled 될 때까지

Await.result(Future.sequence(l map mapValue), duration.Duration.Inf) 

이 기다릴 것이다, 또는 오류가있는 경우) List[Try[Int]]

0

계산의 비동기 특성을 유지하려면 최종 결과 주위에 Future을 유지해야합니다.

(A Future[List[Int]] 및 취득)이 작업을 수행하는 좋은 방법은 (아마 당신이 뭘하려합니다) 다음과 같습니다 있기 때문에,

l.flatMap(f => f.map(v => v)) 

작동하지 않는 :

for { 
    f <- l // Extract individual future 
    v <- f // Extract value from future 
} yield v 

불행하게도이로 변환 FutureGenTraversableOnce을 상속하지 않으며, 그렇지 않아야합니다. 그러나 ListflatMap에 대해이 특성을 필요로합니다.

그러나이 수동으로 수행 할 수 브로 입술 = l.foldRight (Future.successful (List.empty [지능])) { 경우 (X, XS) => xs.flatMap (= VXS 우리는 Future.sequence을 사용할 수 있습니다


> x.map (VX => VX :: VXS)) }는 그렇게 :

Future.sequence(l) 

모든 선물이 완료되고 성공적으로 완료된 선물의 모든 값이 포함될 때만 완료되는 Future[List[Int]]을 반환합니다.

+1

미래 선물 목록을 미래의 목록으로 변환하려면 'Future.sequence'를 사용해야합니다. –

+0

하하하, 알 겠어. 바퀴를 재발 명했다. 업데이트 됨. – gzm0

관련 문제