Dart 生成器(Generator)

2,498 阅读1分钟

参考文档:dart.cn/guides/lang…

当你需要延迟地生成一连串的值时,可以考虑使用生成器函数。Dart内置支持两种形式的生成器方法:

  1. 同步生成器:返回一个Iterable对象。
  2. 异步生成器:返回一个Stream对象。

使用sync*将一个函数标记为同步生成器,并返回Iterable对象,

Iterable<int> naturalsTo(int n) sync* {
  int k = 0;
  while (k < n) yield k++;
}

使用async*标记函数为异步生成器,返回一个Stream对象

Stream<int> asynchronousNaturalsTo(int n) async* {
  int k = 0;
  while (k < n) yield k++;
}

yield有什么用呢🤔?
根据stackoverflow的回答, yield作用同return,都是返回一个值,区别在于yield并不会退出函数。
如上面示例中,yield会返回k的值,但是不退出naturalsTo函数,直到while循环结束才退出naturalsTo函数

Demos

  1. 使用同步生成器生成range函数,用于for循环。
Iterable<int> range(int end, {int step = 1, int start = 0}) sync* {
  if (step == 0) throw Exception('Step cannot be 0');
  if ((step > 0 && start < end) || (step < 0 && start > end)) {
    yield start;
    yield* range(end, step: step, start: start + step);
  }
}

void main() {
  // 递增间隔1(默认)
  for (var value in range(5)) print(value); // [0, 1, 2, 3, 4]

  // 递增间隔2
  for (var value in range(5, step: 2)) print(value); // [0, 2, 4]

  // 递增间隔5
  for (var value in range(5, step: 5)) print(value); // [0]

  // 递减间隔1
  for (var value in range(-1, start: 4, step: -1))
    print(value); // [4, 3, 2, 1, 0]

  // 递减间隔2
  for (var value in range(-1, start: 4, step: -2)) print(value); // [4, 2, 0]

  // 递减间隔5
  for (var value in range(-1, start: 4, step: -5)) print(value); // [4]
}
  1. 生成器语法糖
// 使用语法糖得到一个迭代器
var iterator = [for (var i = 0; i < 5; i++) i];

for (var value in iterator) print(value);

关于Stream

有个表格很清楚的表达了意思, 后续再讲一讲使用吧。

int单值多值
同步intIterator<int>
异步Future<int>Stream<int>