@@ -21,32 +21,43 @@ object Test {
21
21
}
22
22
}
23
23
24
- /** * Producer represents a linear production of values.
24
+ /** * Producer represents a linear production of values with a loop structure .
25
25
*
26
26
* Conceptually the design of the producer has its roots in `unfold` where a stream is a product type of some state
27
- * and a stepper function. The latter transforms the state and returns either the end-of-the-stream or a value and
27
+ * and a stepper function:
28
+ *
29
+ * {{
30
+ * trait Stream[+A]
31
+ * case class Unfold[S, +A](state: S, step: (S) => Option[(S, A)]) extends Stream[+A]
32
+ * }}
33
+ *
34
+ * The latter transforms the state and returns either the end-of-the-stream or a value and
28
35
* the new state. The existential quantification over the state keeps it private: the only permissible operation is
29
- * to pass it to the step function .
36
+ * to pass it to the function. However in `Producer` the elements are not pulled but the step accepts a continuation .
30
37
*
31
- * @tparam A type of the collection elements
38
+ * A Producer defines the three basic elements of a loop structure:
39
+ * - `init` contributes the code before iteration starts
40
+ * - `step` contributes the code during execution
41
+ * - `hasNext` contributes the code of the boolean test to end the iteration
42
+ *
43
+ * @tparam A type of the collection element. Since a `Producer` is polymorphic yet it handles `Expr` values, we
44
+ * can pack together fragments of code to accompany each element production (e.g., a variable incremented
45
+ * during each transformation)
32
46
*/
33
47
trait Producer [A ] { self =>
34
48
type St
35
49
val card : Cardinality
36
50
37
51
/** Initialization method that defines new state, if needed by the combinator that this producer defines.
38
- *
39
- * e.g., `addCounter` which adds a counter
40
52
*
41
53
* @param k the continuation that is invoked after the new state is defined in the body of `init`
42
54
* @return expr value of unit per the CPS-encoding
43
55
*/
44
56
def init (k : St => Expr [Unit ]): Expr [Unit ]
45
57
46
- /** Step method that defines the transformation of data, if applicable .
58
+ /** Step method that defines the transformation of data.
47
59
*
48
- *
49
- * @param st
60
+ * @param st the state needed for this iteration step
50
61
* @param k
51
62
* @return
52
63
*/
@@ -111,10 +122,10 @@ object Test {
111
122
112
123
/** Handles generically the mapping of elements from one producer to another.
113
124
* `mapRaw` can be potentially used threading quoted values from one stream to another. However
114
- * is can be also used by handling any kind of quoted value .
125
+ * is can be also used by declaring any kind of computation we need to perform during each step .
115
126
*
116
127
* e.g., `mapRaw[(Var[Int], A), A]` transforms a stream that declares a variable and holds a value in each
117
- * iteration step to a stream that is not aware of the aforementioned variable.
128
+ * iteration step, to a stream that is not aware of the aforementioned variable.
118
129
*
119
130
* @param f the function to apply at each step. f is of type `(A => (B => Expr[Unit])` where A is the type of
120
131
* the incoming stream. When applied to an element, `f` returns the continuation for elements of `B`
@@ -337,7 +348,12 @@ object Test {
337
348
}
338
349
}
339
350
340
- /**
351
+ /** Make a stream linear
352
+ *
353
+ * Performs reification of the `stream`. It converts it to a function that will, when called, produce the current element
354
+ * and advance the stream -- or report the end-of-stream.
355
+ * The reified stream is an imperative *non-recursive* function, called `adv`, of `Unit => Unit` type. Nested streams are
356
+ * also handled.
341
357
*
342
358
* @param stream
343
359
* @tparam A
@@ -369,6 +385,10 @@ object Test {
369
385
if (~ producer.hasNext(st)) {
370
386
~ producer.step(st, k)
371
387
}
388
+ else {
389
+ val newAdvance = ~ currentAdvance.get
390
+ newAdvance(_)
391
+ }
372
392
})
373
393
case Many => producer.init(st => ' {
374
394
val oldAdvance : Unit => Unit = ~ currentAdvance.get
0 commit comments