【发布时间】:2019-09-10 13:30:17
【问题描述】:
yield 关键字在 Dart 中的实际作用是什么?
【问题讨论】:
yield 关键字在 Dart 中的实际作用是什么?
【问题讨论】:
yield 为周围的async* 函数的输出流添加一个值。类似于return,但不会终止函数。
见https://dart.dev/guides/language/language-tour#generators
Stream asynchronousNaturalsTo(n) async* {
int k = 0;
while (k < n) yield k++;
}
当 yield 语句执行时,它将计算其表达式的结果添加到流中。它不一定会挂起(尽管在当前的实现中会挂起)。
【讨论】:
It's like return, but doesn't terminate the function. 多么完美的方式来解释这一点,而无需深入讨论。谢谢。也就是说,如果你想深入了解这个主题,Tokenet 在下面有一个很好的答案。
已接受答案的链接已损坏,here 是关于async* sync* yield* yield 的官方链接。
如果您对其他语言有一些经验,您可能会停留在这些关键字上。以下是一些克服关键字的提示。
async* sync* yield* yield 被称为生成器函数。您可能主要在 Bloc 模式中使用这些。
async* 也是async,你可以像往常一样使用异步。
sync* 不能用作sync,您将收到提示“修饰符同步必须后跟星号”的错误。
yield 和 yield* 只能与生成器函数(async*sync*)一起使用。
一共有四种组合。
async* yield 将返回 Stream<dynamic>。Stream<int> runToMax(int n) async* {
int i = 0;
while (i < n) {
yield i;
i++;
await Future.delayed(Duration(seconds: 300));
}
}
async* yield* 将调用一个函数并返回 Stream<dynamic>。Stream<int> countDownFrom(int n) async* {
if (n > 0) {
yield n;
yield* countDownFrom(n - 1);
}
}
sync* yield 将返回 Iterable<dynamic>。Iterable<int> genIterates(int max) sync* {
var i = 0;
while (i < max) {
yield i;
i++;
}
}
sync* yield* 将调用一个函数并返回 Iterable<dynamic>。Iterable<int> countDownFrom(int n) sync* {
if (n > 0) {
yield n;
yield* countDownFrom(n - 1);
}
}
如果有任何错误,请发表评论以更正答案。
【讨论】:
yield 语句只能在生成器的函数中使用。
生成器的函数以自然方式生成数据项(如计算、从外部接收、预定义值等)。
当下一个数据项准备好时,yield 语句将该项发送到数据序列中,这本质上是函数的生成结果。
数据序列可以是同步的,也可以是异步的。
在 Dart 语言中,同步数据序列是指Iterable 的实例。
异步数据序列是指Stream的实例。
附言
生成器函数可以无限期地生成数据项,直到函数返回。
但与普通函数不同的是,结果(数据序列)会在函数调用后立即返回,可以立即使用。
在这种情况下,只有在生成器函数将终止(成功或失败)时才能到达数据序列的结尾。
【讨论】:
我认为 yield* 的正确答案是委托给另一个生成器而不是调用函数。 yield* 只是简单地委托给另一个生成器,这意味着当前生成器停止,另一个生成器接管工作,直到它停止生产。在那之后停止生成值,主生成器继续生成自己的值。
感谢@András Szepesházi 鼓励我发表此评论作为答案,希望对您有所帮助。
【讨论】: