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

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

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

Saved successfully!

Ooh no, something went wrong!