조용한 담장

Dart : Generators 본문

Dart

Dart : Generators

iosroid 2019. 11. 22. 18:18

Dart 의 generator 를 살펴보자.

generator 의 용도는

to lazily produce a sequence of values

코드상에서 선언된 순간에 바로 데이터가 처리되지 않고 실제로 사용할 때 데이터가 처리된다.

뒤늦게(실제 데이터가 필요할 때) 처리되는 방식은 동기식 과 비동기식이 있다.

둘 다 yield 를 통해 데이터를 전달하는데 return 과 다른점은 처리할 데이터가 있는 동안은 동작을 완료하지 않고 계속 수행하게 된다.

Synchronous

sync* 속성을 함수가 가지게 된다.

Iterable object 를 리턴한다.

import 'dart:io';

Iterable<int> generatorSync(int n) sync* {
	int k=0;
	while (k < n) {
		yield k++;
		sleep(Duration(seconds: 1));
	}
}

testGS(int n) {
	print('call generatorSync()');
	var gs = generatorSync(n);
	print('generatorSync() ends');
	for (var value in gs) {
		print(value);
	}
}

void main() {
	testGS(5);
}

output:

call generatorSync()
generatorSync() ends
0
1
2
3
4

위 예제를 보면 var gs = generatorSync(n); 코드에서 함수의 동작이 완료되고 모든 결과가 gs 변수에 저장되있을 것 처럼 보인다.

하지만 generatorSync() sync* 가 generator 이기 때문에 for (var value in gs) 에서 실제로 데이터를 처리하는 함수가 동작되어 결과적으로 1초마다 숫자가 출력되는 동작이 이루어 진다.

synchronous generator 의 리턴값은 결국 Iterable 이기 때문에 기본적인 Iterable 클래스 사용법의 차이는 없다.

testGS(int n) {
	print('call generatorSync()');
	var gs = generatorSync(n);
	print('generatorSync() ends');
	gs.forEach(print); // forEach method of Iterable
}

recursive call 도 지원하며 이때는 yield* 를 사용한다.

Iterable<int> generatorSync(int n) sync* {
    if (n > 0) {
        yield n;
        sleep(Duration(seconds: 1));
        yield* generatorSync(n - 1);
    }
}

Asynchronous

generator 동작을 비동기식으로 수행 한다.

async* 속성을 함수가 가지게 된다.

Stream object 를 리턴한다.

import 'dart:io';

Stream<int> generatorAsync(int n) async* {
	int k = 0;
	while (k < n) {
		yield k++;
		sleep(Duration(seconds: 1));
	}
}

testGAS(int n) {
	print('call generatorAsync()');
	generatorAsync(n).listen(print);
}

void main() {
	testGAS(5);
}
Future<int> downloadNothing(int n) async {
	return n;
}

Stream<int> generatorAsync(int n) async* {
	int k = 0;
	while (k < n) {
		yield await downloadNothing(k++);
		sleep(Duration(seconds: 1));
	}
}

recuresive call

Stream<int> generatorAsync(int n) async* {
	if (n > 0) {
		yield await downloadNothing(n);
		sleep(Duration(seconds: 1));
		yield* generatorAsync(n - 1);
	}
}

Reference

Dart Language Tour - Generator

Itarable class

Asynchronous programming: streams

Stream class

'Dart' 카테고리의 다른 글

Dart: null safety  (0) 2020.11.20
Dart 2.7 release  (0) 2019.12.12
Dart : Generics  (0) 2019.11.22
Dart : Collections  (0) 2019.11.19
Dart : print  (0) 2019.11.04
Comments