[英]Difference between yield and yield* in Dart
I wanted to know what's the difference between this two.我想知道这两者有什么区别。 I find this SO post on javascript, Delegated yield (yield star, yield *) in generator functions
我在 javascript, Delegated yield (yield star, yield *) in generator functions上找到了这篇 SO post
From what I understand, yield*
delegates to the another generator and after the another generator stop producing values, then it resumes generating its own values.据我了解,
yield*
委托给另一个生成器,在另一个生成器停止生成值后,它会继续生成自己的值。
Explanation and examples on the dart side would be helpful.飞镖方面的解释和示例会有所帮助。
yield
It is used to emit values from a generator either async or sync.它用于从异步或同步生成器发出值。
Example:例子:
Stream<int> str(int n) async* {
for (var i = 1; i <= n; i++) {
await Future.delayed(Duration(seconds: 1));
yield i;
}
}
void main() {
str(3).forEach(print);
}
Output:输出:
1
2
3
yield*
It delegates the call to another generator and after that generator stops producing the values, it resumes generating its own values.它将调用委托给另一个生成器,在该生成器停止生成值后,它会继续生成自己的值。
Example:例子:
Stream<int> str(int n) async* {
if (n > 0) {
await Future.delayed(Duration(seconds: 1));
yield n;
yield* str(n - 1);
}
}
void main() {
str(3).forEach(print);
}
Output:输出:
3
2
1
yield
returns values from an Iterable or a Stream. yield
从 Iterable 或 Stream 返回值。yield*
is used to recursively call its Iterable or Stream function. yield*
用于递归调用其 Iterable 或 Stream 函数。Let's look an some examples from the Generator Functions - Flutter in Focus video.让我们看一下Generator Functions - Flutter in Focus视频中的一些示例。 We'll just look at the Iterable example, but it's similar for Streams.
我们将只看 Iterable 示例,但它与 Streams 类似。
Here is an Iterable that counts from start
to finish
.这是一个从
start
到finish
计数的 Iterable 。
Iterable<int> getRange(int start, int finish) sync* {
for (int i = start; i <= finish; i++) {
yield i;
}
}
The yield
keyword returns the next value on each iteration. yield
关键字在每次迭代时返回下一个值。
Now let's refactor that function to be recursive.现在让我们将该函数重构为递归。 On the outside it still does the same thing as before:
在外面,它仍然像以前一样做同样的事情:
Iterable<int> getRange(int start, int finish) sync* {
if (start <= finish) {
yield start;
for (final val in getRange(start + 1, finish)) {
yield val;
}
}
}
This works but it's hard to read and not very efficient because of the loop.这有效,但由于循环而难以阅读且效率不高。
Now let's refactor it again using yield*
(pronounced "yield star"):现在让我们使用
yield*
(发音为“yield star”)再次重构它:
Iterable<int> getRange(int start, int finish) sync* {
if (start <= finish) {
yield start;
yield* getRange(start + 1, finish);
}
}
It's still recursive, but now it's easier to read and is more efficient.它仍然是递归的,但现在更容易阅读并且更高效。
I have created a dart pad link to help people experiment:我创建了一个飞镖板链接来帮助人们进行实验:
Yield* is used to yield a whole iterable one value at a time with out using a loop. Yield* 用于在不使用循环的情况下一次产生一个完整的可迭代值。
These 2 functions do exactly the same thing, generates an iterable based on the start and finish values.这两个函数做完全一样的事情,根据开始和结束值生成一个可迭代对象。
Iterable<int> getRangeIteration(int start, int finish) sync* {
for(int i = start; i<= finish; i++){
yield i;
}
}
Iterable<int> getRangeRecursive(int start, int finish) sync* {
if (start <= finish) {
yield start;
yield* getRangeRecursive(start + 1, finish);
}
}
In the first implementation (yield i) would imply type Iterable which matches the function's return type.在第一个实现中(yield i)将暗示与函数的返回类型匹配的 Iterable 类型。
now if in the second implementation instead of现在如果在第二个实现中而不是
yield* getRangeRecursive(start + 1, finish);
if we did如果我们做了
yield getRangeRecursive(start + 1, finish);
we will get a compiler error:我们会得到一个编译器错误:
The type 'Iterable<Iterable<int>>' implied by the 'yield' expression must be assignable to 'Iterable<int>'.
as you can see the yield wraps the Iterable with another Iterable<>, which makes the type Iterable<Iterable>.如您所见,yield 用另一个 Iterable<> 包装了 Iterable,这使得类型为 Iterable<Iterable>。
If we have to do recursion without using yield* we will have to do this:如果我们必须在不使用 yield* 的情况下进行递归,我们将不得不这样做:
Iterable<int> getRangeRecursiveWithOutYieldStar(int start, int finish) sync* {
if (start <= finish) {
yield start;
for (final val in getRangeRecursiveWithOutYieldStar(start + 1, finish)){
yield val;
}
}
}
Which is messy and inefficient.这是混乱和低效的。
So I feel like in my opinion yield* flattens another generator function.所以我觉得在我看来 yield* 扁平化了另一个生成器函数。
A few good resources: Generator Functions - Flutter in Focus video一些不错的资源:生成器函数 - Flutter in Focus 视频
Medium article: What are sync*, async*, yield and yield* in Dart?中篇文章: Dart 中的sync*、async*、yield 和yield* 是什么?
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.