4th International Conference on Principles and Practices ... - MADOC
4th International Conference on Principles and Practices ... - MADOC
4th International Conference on Principles and Practices ... - MADOC
You also want an ePaper? Increase the reach of your titles
YUMPU automatically turns print PDFs into web optimized ePapers that Google loves.
The first implementati<strong>on</strong> follows the idea of linked lists,<br />
where the evaluati<strong>on</strong> of the remainder is delayed until it is<br />
accessed. For that purpose we define an interface LazyTail<br />
whose method eval returns another (lazily evaluated) infinite<br />
stream when evaluated. This implementati<strong>on</strong> corresp<strong>on</strong>ds<br />
to the implementati<strong>on</strong>s presented in [4, 5]. To keep<br />
the code simple we <strong>on</strong>ly show the necessary methods <strong>and</strong><br />
discuss further methods below.<br />
public class LinkedStream implements Stream {<br />
}<br />
public interface LazyTail {<br />
LinkedStream eval();<br />
}<br />
private E head;<br />
private LinkedStream tail; //assigned <strong>on</strong> dem<strong>and</strong><br />
private LazyTail lazyTail; //delayed tail rule<br />
public LinkedStream(E head, LazyTail tail) {<br />
this.head = head;<br />
this.lazyTail = tail;<br />
}<br />
public E getHead(){ return head; }<br />
public LinkedStream getTail(){<br />
if(tail == null) {<br />
tail = lazyTail.eval(); lazyTail = null;<br />
}<br />
return tail;<br />
}<br />
...<br />
Method getHead returns the head element of the stream,<br />
<strong>and</strong> getTail computes <strong>and</strong> returns the tail of the stream.<br />
Since the remainder of a stream should <strong>on</strong>ly be evaluated<br />
<strong>on</strong>ce, we store the result in the field tail <strong>and</strong> free the reference<br />
to the computati<strong>on</strong> procedure so that the garbage<br />
collector can reclaim it.<br />
As an example we define the infinite stream of integers:<br />
public class StreamTest {<br />
static LinkedStream integersFrom(<br />
final int start) {<br />
return new LinkedStream(start,<br />
new LinkedStream.LazyTail(){<br />
public LinkedStream eval(){<br />
return integersFrom(start+1);<br />
}<br />
}<br />
);<br />
}<br />
}<br />
public static void main(String[] args) {<br />
Stream integers = integersFrom(0);<br />
}<br />
Stream s = integers;<br />
for(int i=0; i 0) stream = stream.getTail();<br />
return stream.getHead();<br />
}<br />
For the map method a new stream is generated where the<br />
given functi<strong>on</strong> is mapped <strong>on</strong> each element. The implementati<strong>on</strong><br />
defines an inner class for the lazy tail. Fields accessed<br />
in the outer scope are copied <strong>and</strong> have to be declared final.<br />
The zip <strong>and</strong> select functi<strong>on</strong>s are defined similarly.<br />
public LinkedStream map(<br />
final UnaryFunctor< super E, R> f) {<br />
return new LinkedStream(<br />
f.eval(getHead()),<br />
new LazyTail(){<br />
public LinkedStream eval(){<br />
return getTail().map(f);<br />
}<br />
}<br />
);<br />
}<br />
The prepend method adds a new head element. This<br />
method is problematic as it is strict <strong>on</strong> the stream it is<br />
called. In particular, the head element of the stream to<br />
which a new element is prepended is evaluated as <strong>on</strong>ly the<br />
tail of the series is lazily defined.<br />
public Stream prepend(E head){<br />
return new LinkedStream(<br />
head,<br />
new LazyTail(){<br />
public LinkedStream eval(){<br />
return LinkedStream.this;<br />
}<br />
}<br />
);<br />
}<br />
The evaluati<strong>on</strong> of a stream s to which a new head element<br />
e is added could be avoided, if the c<strong>on</strong>struct<br />
new LinkedStream(e, new LazyTail(){<br />
public LinkedStream eval(){ return s; }<br />
})<br />
were used.<br />
We close this secti<strong>on</strong> with the definiti<strong>on</strong> of the streams<br />
of integers, squares <strong>and</strong> fib<strong>on</strong>acci numbers. Both methods<br />
integersFrom <strong>and</strong> fib<strong>on</strong>acci are recursive <strong>and</strong> c<strong>on</strong>tain calls<br />
to itself in the eval method defined in the an<strong>on</strong>ymous class.<br />
public class StreamTest2 {<br />
public static LinkedStream integersFrom(<br />
final int start) {<br />
return new LinkedStream(<br />
start,<br />
new LinkedStream.LazyTail(){<br />
public LinkedStream eval(){<br />
return integersFrom(start+1);<br />
}<br />
}<br />
);<br />
}<br />
183