미래에 대한 스칼라의 "이해력"
Scala Cookbook ( http://shop.oreilly.com/product/0636920026914.do )을 읽고 있습니다.
이해를 포함하는 미래 사용과 관련된 예가 있습니다.
지금까지 이해에 대한 이해는 컬렉션과 함께 사용할 때 동일한 유형의 다른 컬렉션을 생성한다는 것입니다. 예를 들어 각 futureX유형 Future[Int]이이면 다음도 유형이어야합니다 Future[Int].
for {
r1 <- future1
r2 <- future2
r3 <- future3
} yield (r1+r2+r3)
누군가이 <-코드에서 사용할 때 정확히 어떤 일이 발생하는지 설명해 줄 수 있습니까? 나는 그것이 제너레이터라면 루프를 통해 각 요소를 가져올 것이라는 것을 알고 있습니다.
먼저 이해를 위해. 그것은이 모나드 작업의 몇 통해 추상화 있다고, 많은 여러 번에 대답했다 : map, flatMap, withFilter. 을 사용할 때 <-scalac은이 줄을 모나 딕으로 desugars flatMap:
r <- monad 으로 monad.flatMap(r => ... )
명령형 계산 (모나드의 모든 것)처럼 보이며 계산 결과를 r. 그리고 yield일부는 map호출 로 desugared됩니다 . 결과 유형은의 유형에 따라 다릅니다 monad.
Future특성에는 flatMap및 map기능이 있으므로 이해를 위해 사용할 수 있습니다. 귀하의 예에서 다음 코드로 desugared 될 수 있습니다.
future1.flatMap(r1 => future2.flatMap(r2 => future3.map(r3 => r1 + r2 + r3) ) )
병렬성 제쳐두고
의 실행이 future2의존적 이라면 r1순차 실행을 피할 수는 없지만 미래의 계산이 독립적이면 두 가지 선택이 있습니다. 순차 실행을 시행하거나 병렬 실행을 허용 할 수 있습니다 . 실행 컨텍스트가이를 처리하므로 후자를 적용 할 수 없습니다 .
val res = for {
r1 <- computationReturningFuture1(...)
r2 <- computationReturningFuture2(...)
r3 <- computationReturningFuture3(...)
} yield (r1+r2+r3)
항상 순차적으로 실행됩니다. 이는 desugaring에 의해 쉽게 설명 될 수 있으며, 그 후에 후속 computationReturningFutureX호출은 flatMaps 내부에서만 호출됩니다.
computationReturningFuture1(...).flatMap(r1 =>
computationReturningFuture2(...).flatMap(r2 =>
computationReturningFuture3(...).map(r3 => r1 + r2 + r3) ) )
그러나 이것은 병렬로 실행할 수 있으며 for comprehension은 결과를 집계합니다.
val future1 = computationReturningFuture1(...)
val future2 = computationReturningFuture2(...)
val future3 = computationReturningFuture3(...)
val res = for {
r1 <- future1
r2 <- future2
r3 <- future3
} yield (r1+r2+r3)
여기에 기존 답변을 자세히 설명하기 위해 for이해력이 어떻게 작동 하는지 보여주는 간단한 결과가 있습니다.
조금 긴 기능이지만 살펴볼 가치가 있습니다.
정수 범위를 제공하는 함수
scala> def createIntegers = Future{
println("INT "+ Thread.currentThread().getName+" Begin.")
val returnValue = List.range(1, 256)
println("INT "+ Thread.currentThread().getName+" End.")
returnValue
}
createIntegers: createIntegers: scala.concurrent.Future[List[Int]]
다양한 문자를 제공하는 함수
scala> def createAsciiChars = Future{
println("CHAR "+ Thread.currentThread().getName+" Begin.")
val returnValue = new ListBuffer[Char]
for (i <- 1 to 256){
returnValue += i.toChar
}
println("CHAR "+ Thread.currentThread().getName+" End.")
returnValue
}
createAsciiChars: scala.concurrent.Future[scala.collection.mutable.ListBuffer[Char]]
이러한 함수 호출 사용하여 내 이해에 대한합니다.
scala> val result = for{
i <- createIntegers
s <- createAsciiChars
} yield i.zip(s)
Await.result(result, Duration.Inf)
result: scala.concurrent.Future[List[(Int, Char)]] = Future(<not completed>)
아래 줄에 대해 우리는 모든 함수 호출이 동기적임을 확인할 수 createAsciiChars있습니다. 즉, 함수 호출은 실행이createIntegers 완료 될 때까지 실행되지 않습니다 .
scala> INT scala-execution-context-global-27 Begin.
INT scala-execution-context-global-27 End.
CHAR scala-execution-context-global-28 Begin.
CHAR scala-execution-context-global-28 End.
이러한 기능 만들기 createAsciiChars, createIntegers외부 전화 for함축는 비동기 실행됩니다.
It allows r1, r2, r3 to run in parallel, if possible. It may not be possible, depending things like how many threads are available to execute Future computations, but by using this syntax you are telling the compiler to run these computations in parallel if possible, then execute the yield() when all have completed.
ReferenceURL : https://stackoverflow.com/questions/19045936/scalas-for-comprehension-with-futures
'Program Club' 카테고리의 다른 글
| 마우스 / 캔버스 X, Y에서 Three.js 세계 X, Y, Z (0) | 2020.12.29 |
|---|---|
| pandas.Series 히스토그램 플롯을 파일에 저장 (0) | 2020.12.29 |
| 클래스와 메서드에서 @Transactional을 정의하는 것의 차이점은 무엇입니까 (0) | 2020.12.29 |
| LOAD DATA LOCAL, 첫 줄을 어떻게 건너 뛰나요? (0) | 2020.12.29 |
| HTTPS가없는 상태에서 Javascript를 사용하여 HTTP를 통해 안전하게 비밀번호를 보내는 방법은 무엇입니까? (0) | 2020.12.29 |