}
{ $description "Attempts to run the " { $snippet try } " quotation. If a " { $link stop-generator } " error is thrown, then the " { $snippet except } "quotation will be run instead." } ;
+HELP: exhausted?
+{ $values
+ { "gen" generator } { "?" boolean }
+}
+{ $description "Check whether a generator has already been exhausted." } ;
+
HELP: gen-coroutine
{ $values
{ "quot" quotation } { "gen" generator }
}
{ $description "Pause computation and yield a value to the caller, with the expectation for a value to be returned before computation is resumed." } ;
+HELP: yield-from
+{ $values
+ { "gen" generator }
+}
+{ $description "Delegate computation to the specified generator until it is exhausted, before resuming computation in the current generator." } ;
+
ARTICLE: "generators" "generators"
{ $vocab-link "generators" }
;
{ { 1 2 3 } } [ no-inp-gen take-all ] unit-test
{ { } } [ [ ] <generator> take-all ] unit-test
+
+GEN: yf-test ( -- g ) no-inp-gen yield-from no-inp-gen yield-from ;
+{ { 1 2 3 1 2 3 } } [ yf-test take-all ] unit-test
+
+{ t } [ no-inp-gen [ take-all drop ] [ exhausted? ] bi ] unit-test
+{ f } [ no-inp-gen exhausted? ] unit-test
: ?next ( gen -- val/f end? ) [ next f ] [ drop f t ] catch-stop-generator ;
: ?next* ( v gen -- val/f end? ) [ next* f ] [ 2drop f t ] catch-stop-generator ;
: take ( gen n -- seq ) [ swap '[ drop _ ?next [ , t ] unless ] all-integers? drop ] { } make ;
-: take-all ( gen -- seq ) [ '[ _ ?next [ , t ] unless ] loop ] { } make ;
+: take-all ( gen -- seq ) '[ _ ?next not ] [ ] produce nip ;
+
+: yield-from ( gen -- ) '[ _ ?next [ drop f ] [ yield t ] if ] loop ;
+
+: exhausted? ( gen -- ? ) state>> not ;