Export of DataStream
generator: % -> Generator T
Usage
T == Integer;
l: List T := [2,3,5,7,11,0];
s: DataStream T := stream generator l;
nonzeros: List T := [x for x in s while x > 0];
Description
Generate all elements of the stream.
This function always returns a generator that gives infinitely many elements. generator(x) is equivalent to the following code.
generate for i in 0.. repeat yield x.i;
Remarks
Note that g := generator(new()) does not give the empty generator, but rather a runtime error if g is asked for an element.
Export of DataStream
elements: (%, startFromIndex: MachineInteger == 0) -> Generator T
Usage
s: DataStream Integer := stream 4;
g1: Generator Integer := generator s;
l1: List Integer := [i for i in g1 for k in 0..9];
assert(l1 = [4,4,4,4,4,4,4,4,4,4]);
g2: Generator Integer := elements s;
l2: List Integer := [i for i in g2 for k in 0..9];
assert(l2 = [4]);
t: DataStream Integer := stream generator [2,3,5,7,11];
g3: Generator Integer := elements(t, 2);
l3: List Integer := [i for i in g3 for k in 0..9];
assert(l3 = [5,7,11]);
g4: Generator Integer := elements(t, 10);
l4: List Integer := [i for i in g4 for k in 0..9];
assert(l4 = [11]);
Description
Generate all elements of the stream until the last elements repeats.
This function returns a generator that generates elements until the stream is known to be constant. It starts from the index in s that is given as a second argument.
The function elements is the inverse of stream in the sense that
is basically a copy of the original generator g. But note that g is consumed and the cache of the stream stream(g) is filled while extracting elements from h.Similarly, r := stream(elements(s)) is a copy of the stream s. But again, while elements are extracted from r, also the number of computed elements of s might change.
Calling r := stream(elements(s, 1)) creates a stream that is like the orignal s, but without the head element.
Remarks
It is no problem to access (and thus internally modify) the stream s while iterating over elements(s). For example, the following code correctly generates 6 elements.
g: Generator Integer := generator [1,2,3,4,5,6];
s: DataStream Integer := stream g;
a: List Integer := empty;
b: List Integer := empty;
for i in 0.. for x in elements s repeat {
a := cons(x, a);
b := cons(s.(2*i), b);
}
Export of DataStream
apply: (%, MachineInteger) -> T
Usage
T == Integer;
l: List T := [2,3,5,7,11,0];
s: DataStream T := stream generator l;
x := s.3;
y := apply(s, 0);
Description
Access an entry of the stream.
A DataStream models an infinite object of the form
(172) |
If in apply(s, i) the parameter i ≥#s and the stream s is not known to be constant, then new elements must be computed from the internally stored generator of s. During that process, the internal array must grow. For that we use the following resize! function. After its execution the cache corresponding to x must have room for sz entries (0,1,…sz− 1).
g: Generator T == generate {};
s: DataStream T == stream g;
t: T := s.0; -- exception here
In case the i-th entry has already been computed, we simply take it from the cache. If we know a stream x is eventually constant, then we can simply return the constant value by accessing the cache at index #x − 1.
Here we know that the element we want to return, is not yet computed. So first we make room so that the element with index i can be stored into the cache.
Now we fill the cache with all the elements up to the i-th.