expand
각 원소를 이터러블로 매핑한 다음 결과를 한 단계 평탄화합니다 — Iterable.expand와 동일한 계약입니다.
강의
expand는 map 뒤에 한 단계 평탄화를 붙인 것입니다.
각 원소가 결과의 컬렉션으로 바뀌고, 그 컬렉션들이 이어 붙여져
하나의 평평한 지연 시퀀스가 됩니다. "입력 하나에 출력 여럿"이 필요할 때
쓰는 도구입니다 — 문장을 단어로 쪼개거나, 사용자를 주문 목록으로 펼치거나,
범위를 쌍으로 바꾸는 식이죠. expand는 Dart다운 이름이고
(Iterable.expand와
짝을 이룹니다), fxdart는 FxTS식 표기인 flatMap도 함께
받습니다 — 같은 연산자입니다.
FxTS와 다른 점: FxTS에서는 콜백이 일반 값과 이터러블을
섞어서 반환해도 연산자가 DeepFlat 타입 마법으로
무엇을 평탄화할지 알아냅니다. Dart에는 그런 조건부 타입이 없기 때문에,
Dart 포팅판은 f가 항상
Iterable<B>를 반환하도록 요구합니다 —
Iterable.expand와
똑같습니다. 입력 하나당 값 하나만 내보내려면 원소가 하나인 리스트
([x])를, 아무것도 내보내지 않으려면 빈 리스트를 반환하세요.
비동기 쪽에서는 expandAsync의 내부 상태 머신이 pull 사이사이에
"지금 어느 하위 이터러블을 소진하는 중인지"를 추적해야 하므로 상류를
직렬로 소비합니다. 여기에 .concurrent(n)을 감싸면
이미 준비된 항목을 끌어오는 속도만 빨라질 뿐, 콜백 안에서 일어나는
await 자체는 빨라지지 않습니다. 원소마다 비동기 작업을
동시에 처리하고 싶다면 그 작업을 먼저
.map(...).concurrent(n) 단계에서 수행한 뒤, 이미 완료된
리스트들을 .expand((list) => list)로 평탄화하세요 —
데모 2를 보세요.
데모 1 · 기본
콜백은 반드시 Iterable을 반환해야 합니다 — 여기서는 원소 2개짜리
리스트와 String.split 호출을 씁니다:
데모 2 · 비동기, 동시성을 제대로 얻는 방법
느린 await는 .map(...).concurrent(n) 단계에 두고,
expand는 그 결과를 동기적으로 평탄화하게 하세요:
직접 해 보기
연습: expand로 각 문장을 단어로 쪼개어
하나의 평평한 단어 리스트를 만들어 보세요.