我想知道無限遞回生成器是否會導致堆疊溢位錯誤。我不確定無限遞回是否是生成器的正確用例,但我在檔案中找不到任何關于它的線索。
讓我們看這個例子:
import 'dart:async';
Stream<bool> infiniteStream(bool t) async* {
yield t;
await Future.delayed(Duration(milliseconds: 1));
yield* infiniteStream(!t);
}
void main() async {
await for (final value in infiniteStream(true)) {
print(value);
}
}
這是對生成器的正確使用嗎?還是會在很長一段時間后導致錯誤/性能問題?如果這不正確,那么實作可以向自身添加事件以回應接收到的事件的無限流的正確方法是什么?
我還注意到,如果沒有 Future.delayed(),dartpad 會崩潰。
uj5u.com熱心網友回復:
它肯定會溢位一些東西,但在這種情況下它可能是堆,所以這不太可能很快發生。(不過,如果你讓它運行足夠長的時間,它就會發生。)
因為代碼是異步的,實際的堆疊跟蹤只從事件回圈到異步計算的繼續。它不保留啟動異步計算的堆疊(因為該堆疊很久以前已經有一個流或未來回傳給它)。它可能必須通過遞回深度中線性的偵聽器鏈將產生的值傳播回來Stream,但這些將是堆分配的。
這是基于當前的實施策略。沒有什么可以阻止基于單獨堆疊的異步計算實作,它可以為yield*操作(或await asyncFunction()呼叫)重用相同的堆疊。如果發生這樣的實作,則不再保證您不會看到此類代碼的堆疊溢位。
類似地,一個sync*函式如果你做無界遞回可能會導致堆疊溢位yield*,但目前也只使用堆空間。
轉載請註明出處,本文鏈接:https://www.uj5u.com/caozuo/434922.html
上一篇:存盤串列的所有r個組合
