Index: docs/language/dartLangSpec.tex |
=================================================================== |
--- docs/language/dartLangSpec.tex (revision 42940) |
+++ docs/language/dartLangSpec.tex (working copy) |
@@ -3505,13 +3505,29 @@ |
} |
\LMHash{} |
-If $f$ is marked \SYNC* (\ref{functions}), then a fresh instance $i$ implementing the built-in class \code{Iterable} is associated with the invocation and immediately returned. When iteration over the iterable is started, by getting an iterator $j$ from the iterable and calling \code{moveNext()} on it, execution of the body of $f$ will begin. When $f$ terminates, $j$ is positioned after its last element, so that its current value is \NULL{} and the current call to \code{moveNext()} on $j$ returns false, as will all further calls. |
+If $f$ is marked \SYNC* (\ref{functions}), then a fresh instance $i$ implementing the built-in class \code{Iterable} is associated with the invocation and immediately returned. The behavior of the \code{Iterable} must be compatible with an extension of the \code{IterableBase} class in the \code{dart:core} library. |
Lasse Reichstein Nielsen
2015/01/21 10:19:21
No need to mention `IterableBase` in normative tex
gbracha
2015/01/21 19:19:19
I used IterableBase because I don't find the speci
|
-% Can we get more than one iterator from this Iterable? I'd say yes. And if so, do they restart the computation or do they iterate over previously computed results. My guess is the latter. |
-% I also assume we extend the IterableBase implementation; otherwise one can pre-compute |
-% it all |
+\commentary{ |
+A Dart implementation will need to provide a specific implementation of \code{Iterable} that will be returned by \SYNC* methods. The only method that needs to be added by the Dart implementation is \code{iterator}. In all other respects, the behavior of the \code{Iterable} is dictated by the use of \code{IterableBase}. |
+} |
\LMHash{} |
+When iteration over the iterable is started, by getting an iterator $j$ from the iterable and calling \code{moveNext()} on it, execution of the body of $f$ will begin. When $f$ terminates, $j$ is positioned after its last element, so that its current value is \NULL{} and the current call to \code{moveNext()} on $j$ returns false, as will all further calls. |
+ |
+Each iterator starts a separate computation. If the \SYNC* function is impure, the sequence of values yielded by each iterator may differ. |
+ |
+\commentary{ |
+One can derive more than one iterator from a given iterable. Note that operations on the iterable itself can create distinct iterators. An example would be \code{length}. It is conceivable that different iterators might yield sequences of different length. Unless the underlying \SYNC* function is a mathematically pure function, it is probably best not to create multiple iterators on the result of a \SYNC* function, either directly or indirectly. |
Lasse Reichstein Nielsen
2015/01/21 10:19:21
I wouldn't discourage creating multiple iterators.
gbracha
2015/01/21 19:19:19
Done.
|
+} |
+ |
+Each iterator runs with its own copies of all local variables; in particular, each iterator has the same initial arguments, even if their bindings are modified by the function. |
Lasse Reichstein Nielsen
2015/01/21 10:19:21
Good catch! There really is one invocation of the
hausner
2015/01/21 17:33:03
What does "its own copies of all local variables"
gbracha
2015/01/21 19:19:18
Shallow copy.
|
+\commentary{ |
+Two executions of an iterator interact only via state outside the function. |
+} |
+% The alternative would be to cache the results of an iterator in the iterable, and check the cache at each \YIELD{}. This would have strange issues as well. The yielded value might differ from the expression in the yield. And it is a potential memory leak as the cache is kept alive by any iterator. |
+ |
+ |
+\LMHash{} |
If $f$ is synchronous and is not a generator (\ref{functions}) then execution of the body of $f$ begins immediately. When $f$ terminates the current return value is returned to the caller. |