4th International Conference on Principles and Practices ... - MADOC
4th International Conference on Principles and Practices ... - MADOC
4th International Conference on Principles and Practices ... - MADOC
Create successful ePaper yourself
Turn your PDF publications into a flip-book with our unique Google optimized e-Paper software.
}<br />
private static LinkedStream fib<strong>on</strong>acci(<br />
final int a, final int b){<br />
return new LinkedStream(<br />
a,<br />
new LinkedStream.LazyTail () {<br />
public LinkedStream eval(){<br />
return fib<strong>on</strong>acci(b, a+b);<br />
}<br />
}<br />
);<br />
}<br />
public static void main(String[] args) {<br />
Stream integers = integersFrom(0);<br />
System.out.println(integers);<br />
}<br />
Stream squares = integers.map(<br />
new Stream.UnaryFunctor(){<br />
public Integer eval(Integer x){<br />
return x*x;<br />
}<br />
}<br />
);<br />
System.out.println(squares);<br />
Stream fib<strong>on</strong>accy = fib<strong>on</strong>acci(0, 1);<br />
System.out.println(fib<strong>on</strong>accy);<br />
This program generates the following output:<br />
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 ...<br />
0 1 4 9 16 25 36 49 64 81 100 121 144 169 196 ...<br />
0 1 1 2 3 5 8 13 21 34 55 89 144 233 377 ...<br />
3. ARRAY STREAMS<br />
In class LinkedStream an infinite stream is represented<br />
as a linked list. Accessing the n th element requires O(n)<br />
operati<strong>on</strong>s. An alternative would be to store the stream elements<br />
in an array or a hash table where they can be accessed<br />
in c<strong>on</strong>stant time. This is how array lists are implemented<br />
in the Java collecti<strong>on</strong> framework. This strategy can also<br />
be applied to infinite streams. Instead of a functor for the<br />
computati<strong>on</strong> of the remainder of a stream a functor for the<br />
computati<strong>on</strong> of the n th term of the stream is provided.<br />
We present a simple implementati<strong>on</strong> of this approach.<br />
Class ArrayStream c<strong>on</strong>tains <strong>on</strong>ly a minimal set of methods;<br />
additi<strong>on</strong>al methods of the Stream interface are discussed below.<br />
import java.util.HashMap;<br />
public class ArrayStream implements Stream {<br />
public interface Coefficients {<br />
E get(int index);<br />
}<br />
private Coefficients lazyCoeff;<br />
private HashMap coeff =<br />
new HashMap();<br />
public ArrayStream(Coefficients lazyCoeff){<br />
if(lazyCoeff == null) throw<br />
new IllegalArgumentExcepti<strong>on</strong>();<br />
this.lazyCoeff = lazyCoeff;<br />
}<br />
public E get(int index){<br />
if (index < 0) yhrow new<br />
IndexOutOfBoundsExcepti<strong>on</strong>("negative index");<br />
Integer n = index;<br />
}<br />
}<br />
if(!coeff.c<strong>on</strong>tainsKey(n))<br />
coeff.put(n, lazyCoeff.get(index));<br />
return coeff.get(n);<br />
public E getHead(){ return get(0); }<br />
public ArrayStream getTail(){<br />
return new ArrayStream(<br />
new Coefficients(){<br />
public E get(int index){<br />
return ArrayStream.this.get(index+1);<br />
}<br />
}<br />
);<br />
}<br />
Method get first checks whether the requested term of the<br />
stream has already be computed. If not, it is computed with<br />
the provided coefficient method. getHead simply returns the<br />
first term, <strong>and</strong> getTail c<strong>on</strong>structs a new ArrayStream which<br />
returns the terms shifted by <strong>on</strong>e. Note, that the terms of<br />
the tail stream are stored in that stream’s coefficient map<br />
as well. This waste of storage could be avoided (at the cost<br />
of an additi<strong>on</strong>al method call) with a no-cache flag added to<br />
class ArrayStream.<br />
We present the implementati<strong>on</strong> of two additi<strong>on</strong>al methods<br />
of the Stream interface. The prepend method defines a new<br />
coefficient method which returns the new head element <strong>and</strong><br />
the terms of the original stream shifted by <strong>on</strong>e. In c<strong>on</strong>trast<br />
to the prepend method of LinkedStream the evaluati<strong>on</strong> of<br />
the head element of the this stream is not forced.<br />
public Stream prepend(final E head){<br />
return new ArrayStream(<br />
new Coefficients(){<br />
public E get(int index){<br />
if(index == 0) return head;<br />
else return ArrayStream.this.get(index-1);<br />
}<br />
}<br />
);<br />
}<br />
The select functi<strong>on</strong> is more tricky for array streams than<br />
for linked streams. If the k th element is accessed, the elements<br />
with index 0 up to k − 1 already have to be known.<br />
This is ensured in the implementati<strong>on</strong> below by accessing<br />
the directly preceding element which is either taken out of<br />
the hash map or computed. Moreover, the coefficient procedure<br />
has to maintain an index into the original stream.<br />
public Stream select(final Selector< super E> s){<br />
final ArrayStream stream = new ArrayStream();<br />
stream.lazyCoeff = new Coefficients(){<br />
int pos = 0;<br />
public E get(int index){<br />
if(index > 0) stream.get(index-1);<br />
E x = null;<br />
do {x = ArrayStream.this.get(pos++);}<br />
while(!s.select(x));<br />
return x;<br />
}<br />
};<br />
return stream;<br />
}<br />
Unfortunately, the use of select operati<strong>on</strong>s leads to deeper<br />
recursi<strong>on</strong> levels with this stream representati<strong>on</strong> <strong>and</strong> may end<br />
earlier in a StackOverflowError. Moreover, r<strong>and</strong>om access<br />
is not used in typical stream applicati<strong>on</strong>s.<br />
184