Dart 生成器函数 (yield / yield*)

Dart Generator Functions (yield / yield*)

我想了解生成器函数在 dart/flutter 中的工作原理。

flutter 团队 Generator Functions - Flutter in Focus 有一段视频,他们在其中讨论了以下示例。

Iterable<int> getRange(int start, int finish) sync* {
  if (start <= finish) {
    yield start;
    print('start: $start');

    
    for (final val in getRange(start+1, finish)) {
      yield val;
      print('val: $val');
    }
  }
}

只是没有打印线。

我像这样在 main 中调用了那个函数

void main() async {
    getRange(0, 3).forEach(print);
}

得到以下结果:

0
start: 0
1
val: 1
start: 1
2
val: 2
val: 2
start: 2
3
val: 3
val: 3
val: 3
start: 3

我不明白输出结果的部分来自

1
val: 1
start: 1

为什么start: 1val: 1之后。我不知何故不明白递归与收益率的结合是如何工作的。还有当 yield val; 被读取时会发生什么。

代码写得不好的一个很好的例子,做奇怪的事情,很难理解,因为代码一开始就写得很糟糕。为了使调试更容易,我将 start 变量添加到 print 语句中。还从您的 main() 中删除了 async,因为这里没有 运行 异步:

Iterable<int> getRange(int start, int finish) sync* {
  if (start <= finish) {
    yield start;
    print('(start = $start) start: $start');

    for (final val in getRange(start + 1, finish)) {
      yield val;
      print('(start = $start) val: $val');
    }
  }
}

void main() {
  getRange(0, 3).forEach(print);
}

输出:

0
(start = 0) start: 0
1
(start = 0) val: 1
(start = 1) start: 1
2
(start = 0) val: 2
(start = 1) val: 2
(start = 2) start: 2
3
(start = 0) val: 3
(start = 1) val: 3
(start = 2) val: 3
(start = 3) start: 3

所以你现在问的部分是:

1
(start = 0) val: 1
(start = 1) start: 1

您程序中的一个重要细节是您在 yield 之前 print()。因此,当您执行 yield 1 时,该值将作为第一件事移动到 main() 中的 print 语句。然后您可以看到您的 for-loop 将在请求下一个值之前执行 val 打印,这将使 start = 1 循环继续。

sync* 方法中的

yield 表示方法传递值并停止执行该方法,直到请求新值。