15.01.2015 Views

4th International Conference on Principles and Practices ... - MADOC

4th International Conference on Principles and Practices ... - MADOC

4th International Conference on Principles and Practices ... - MADOC

SHOW MORE
SHOW LESS

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

Hooray! Your file is uploaded and ready to be published.

Saved successfully!

Ooh no, something went wrong!