문서의 선택한 두 판 사이의 차이를 보여줍니다.
양쪽 이전 판 이전 판 다음 판 | 이전 판 | ||
비동기_프로그래밍과_scala [2020/08/09 07:02] cumul0529 잘못 옮긴 용어 수정 |
비동기_프로그래밍과_scala [2020/08/09 07:39] (현재) cumul0529 [함수형 프로그래밍과 타입 클래스] 마크업 수정 |
||
---|---|---|---|
줄 157: | 줄 157: | ||
<code scala> | <code scala> | ||
- | // 영 좋지 못한 | + | // 나쁜 |
def timesFourInParallel(n: | def timesFourInParallel(n: | ||
onFinish => { | onFinish => { | ||
줄 178: | 줄 177: | ||
</ | </ | ||
- | 바로 이것이 비결정론의 실례(實例)입니다. 두 개의 작업이 종료되는 순서가 보장되지 않기 때문에 우리는 동기화를 수행하는 소규모의 상태 기계(state machine)를 구현해야 합니다. | + | 바로 이것이 비결정론의 실제 예시입니다. 두 개의 작업이 종료되는 순서가 보장되지 않기 때문에 우리는 동기화를 수행하는 소규모의 상태 기계(state machine)를 구현해야 합니다. |
먼저 상태 기계의 ADT를 정의합니다. | 먼저 상태 기계의 ADT를 정의합니다. | ||
줄 196: | 줄 195: | ||
<code scala> | <code scala> | ||
- | // JVM에서는 | + | // JVM에서는 |
def timesFourInParallel(n: | def timesFourInParallel(n: | ||
onFinish => { | onFinish => { | ||
줄 416: | 줄 414: | ||
===== Future와 Promise ===== | ===== Future와 Promise ===== | ||
- | '' | + | '' |
< | < | ||
줄 446: | 줄 444: | ||
// 값 변형 | // 값 변형 | ||
def map[U](f: T => U)(implicit ec: ExecutionContext): | def map[U](f: T => U)(implicit ec: ExecutionContext): | ||
+ | |||
// 연속 실행 ;-) | // 연속 실행 ;-) | ||
def flatMap[U](f: | def flatMap[U](f: | ||
+ | |||
// ... | // ... | ||
} | } | ||
줄 454: | 줄 454: | ||
'' | '' | ||
- | * [[https:// | + | * [[https:// |
- | * [[https:// | + | * [[https:// |
* 단일한 값을 흘려보내고(stream) 나타냅니다(show). 메모아이제이션이 적용되었기 때문입니다. 따라서 작업 완료에 대한 소비자(listener)는 최대 한 번까지만 호출됩니다. | * 단일한 값을 흘려보내고(stream) 나타냅니다(show). 메모아이제이션이 적용되었기 때문입니다. 따라서 작업 완료에 대한 소비자(listener)는 최대 한 번까지만 호출됩니다. | ||
줄 529: | 줄 529: | ||
<code scala> | <code scala> | ||
- | // 영 좋지 못한 | + | // 나쁜 |
def sum(list: List[Future[Int]])(implicit ec; ExecutionContext): | def sum(list: List[Future[Int]])(implicit ec; ExecutionContext): | ||
async { | async { | ||
줄 550: | 줄 550: | ||
<code scala> | <code scala> | ||
def timesFourInParallel(n: | def timesFourInParallel(n: | ||
- | // Future는 | + | // Future는 |
val fa = timesTwo(n) | val fa = timesTwo(n) | ||
val fb = timesTwo(n) | val fb = timesTwo(n) | ||
줄 568: | 줄 568: | ||
</ | </ | ||
- | 이 방법도 초보자에게는 조금 충격적일 수도 있습니다. 여기서 '' | + | 이 방법도 초보자에게는 조금 충격적일 수도 있습니다. 여기서 '' |
==== 재귀 실행 ==== | ==== 재귀 실행 ==== | ||
줄 633: | 줄 633: | ||
CPU-bound 작업은 [[https:// | CPU-bound 작업은 [[https:// | ||
- | > **원주** 이 벤치마크 결과는 한정적입니다. 여전히 '' | + | > **원주** 이 벤치마크 결과에는 한계가 있습니다. 여전히 '' |
===== Task와 Scala의 IO 모나드 ===== | ===== Task와 Scala의 IO 모나드 ===== | ||
- | '' | + | '' |
[[https:// | [[https:// | ||
줄 649: | 줄 649: | ||
요약하자면 '' | 요약하자면 '' | ||
- | * 느긋하고 비동기적인 연산을 표현합니다. | + | * Lazy하고 비동기적인 연산을 표현합니다. |
* 하나 혹은 여러 개의 소비자(consumer)에게 오직 하나의 값만을 전달하는 생산자(producer)를 표현합니다. | * 하나 혹은 여러 개의 소비자(consumer)에게 오직 하나의 값만을 전달하는 생산자(producer)를 표현합니다. | ||
- | * 느긋하게 계산되기 때문에, '' | + | * Lazy evaluation을 수행하기 때문에, '' |
* 메모아이제이션이 가능합니다. | * 메모아이제이션이 가능합니다. | ||
* 반드시 다른 논리 스레드에서 실행되어야 하는 것은 아닙니다. | * 반드시 다른 논리 스레드에서 실행되어야 하는 것은 아닙니다. | ||
줄 664: | 줄 664: | ||
Monix의 구현에서 '' | Monix의 구현에서 '' | ||
- | ^ ^ 조급한 계산 | + | ^ |
- | | 동기 작업 | + | | 동기 작업 |
| ::: | ::: | [[https:// | | ::: | ::: | [[https:// | ||
| 비동기 작업 | (A => Unit) => Unit | (A => Unit) => Unit | | | 비동기 작업 | (A => Unit) => Unit | (A => Unit) => Unit | | ||
줄 672: | 줄 672: | ||
==== 연속 실행 ==== | ==== 연속 실행 ==== | ||
- | [[비동기_프로그래밍과_scala&do=# | + | [[비동기_프로그래밍과_scala# |
<code scala> | <code scala> | ||
줄 690: | 줄 690: | ||
</ | </ | ||
- | 이 코드는 '' | + | 이 코드는 '' |
이제 [[비동기_프로그래밍과_scala# | 이제 [[비동기_프로그래밍과_scala# | ||
줄 726: | 줄 726: | ||
// 나쁜 예 (이 코드는 여전히 연속 실행됩니다) | // 나쁜 예 (이 코드는 여전히 연속 실행됩니다) | ||
def timesFour(n: | def timesFour(n: | ||
- | // Task는 | + | // Task는 |
val fa = timesTwo(n) | val fa = timesTwo(n) | ||
val fb = timesTwo(n) | val fb = timesTwo(n) | ||
- | // 느긋한 계산으로 인해 값이 연속으로 계산됩니다. | + | // Lazy evaluation으로 인해 값이 연속으로 계산됩니다. |
for (a <- fa; b <- fb) yield a + b | for (a <- fa; b <- fb) yield a + b | ||
} | } | ||
줄 747: | 줄 747: | ||
'' | '' | ||
- | '' | + | '' |
<code scala> | <code scala> | ||
줄 772: | 줄 772: | ||
'' | '' | ||
- | 이것이 바로 Hakell의 '' | + | 이것이 바로 Hakell의 '' |
그렇다면 '' | 그렇다면 '' | ||
- | 가능합니다. 우리는 이미 순차 실행을 추상화하는 '' | + | 가능합니다. 우리는 이미 순차 실행을 추상화하는 '' |
마침 Scala는 상류 타입(higher kinded types)을 지원하는 몇 안되는 언어에 속하고 [[https:// | 마침 Scala는 상류 타입(higher kinded types)을 지원하는 몇 안되는 언어에 속하고 [[https:// | ||
줄 784: | 줄 784: | ||
> 하지만 그러한 설명 방식은 Scala와 사용자 모두에게 민폐입니다. 다른 언어에서 저 개념들은 단순히 설명하기 어려운 디자인 패턴에 불과합니다. 대부분의 다른 언어들은 형에 대한 표현성이 부족하기 때문입니다. 저 개념들을 표현할 수 있는 언어는 손에 꼽습니다. 언어 사용자의 입장에서도 문제가 생겼을 때 저 개념들을 모른 채 관련된 자료를 검색하는 것은 매우 고통스러운 일입니다. | > 하지만 그러한 설명 방식은 Scala와 사용자 모두에게 민폐입니다. 다른 언어에서 저 개념들은 단순히 설명하기 어려운 디자인 패턴에 불과합니다. 대부분의 다른 언어들은 형에 대한 표현성이 부족하기 때문입니다. 저 개념들을 표현할 수 있는 언어는 손에 꼽습니다. 언어 사용자의 입장에서도 문제가 생겼을 때 저 개념들을 모른 채 관련된 자료를 검색하는 것은 매우 고통스러운 일입니다. | ||
> | > | ||
- | > 또 저는 이것이 모르는 것에 대한 본능적인 공포에서 나오는 일종의 [[https:// | + | > 또 저는 이것이 모르는 것에 대한 본능적인 공포에서 나오는 일종의 [[https:// |
==== Monad (연속 실행과 재귀 실행) ==== | ==== Monad (연속 실행과 재귀 실행) ==== |