Export of DataStream
set!: (%, MachineInteger, T) -> T
Usage
T == Integer;
l: List T := [4,3,5,2,6,1];
s: DataStream T := stream generator l;
s.3 := 1;
u: List T := [t-z for t in l for z in s];
a: DataStream := stream 0;
a.2 := 3;
v: List T := [z for t in 0..4 for z in a]
assert(v=[0,0,3,0,0];
Description
Destructively modify an entry of a stream.
The function uses the existing stream data and modifies it in the given place.
If the stream s is known to be constant, then it is also constant after the call set!(s, n, t).
Remarks
This function changes the value of the stream at exactly one place.
Let us try to set the i-th element of a stream x to t. The simplest approach is to access the i-th element in order to compute all elements up to xi and then override the i-th entry. According to the way we have stored elements in the stream, the following situation could happen. The stream will eventually be constant, but we have not yet stepped the generator enough to know for sure. In fact, i could just be the position of the constant element that should be repeated infinitely often and the internal generator is empty. If in that case we simply override xi by a new element t the stream would be modified in infinitely many places, since it would give xn = t for all n ≥ i. We simply exclude that case by computing up to the index i + 1.
Still, there are two cases.
In the first case, we can simply override the element in the cache.
In the second case the stream must be known to be constant.
Then we make room in the cache to hold the new element t and the old constant u as the next element so that u is also the (repeated) constant of the new stream.
And we fill the uninitialized entries with the constant u from above.
Putting it all together yields the following chunk.
Export of DataStream
set!: (%, Generator T) -> ()
Usage
T == Integer;
l: List T := [4,3,5,2,6,1];
s: DataStream T := stream generator l;
a := s.3;
g: Generator l;
set!(s, g);
b := s.5;
fib: DataStream T := new();
g: Generator T := generate {
yield 1;
yield 1;
for n in 0.. repeat yield fib.n + fib.(next n);
}
set!(fib, g);
f: List T := [x for x in fib while x < 50];
Description
Construct a stream using an old structure.
The function uses the existing stream data of its first argument and creates a stream that does not modify the values that are already cached, but uses the new generator g for the generation of the next elements.
If the stream s is known to be constant, then after the call set!(s, g), the function call constant?(s) returns false.
Note that the stream is 0-based. In the usage example above, a = 2 (the fourth element of the list), and b = 3. The value of f is [1,1,2,3,5,8,13,21,34].