Programming in Scala”
fpiscompanion
fpiscompanion
Create successful ePaper yourself
Turn your PDF publications into a flip-book with our unique Google optimized e-Paper software.
Chapter notes 16<br />
This may seem like it shouldn’t work. The stream is referenc<strong>in</strong>g itself <strong>in</strong> its own tail! But the trick<br />
is that the #:: constructor is non-strict <strong>in</strong> its second argument. The evaluation of cyclic will stop<br />
without expand<strong>in</strong>g the expression 1 #:: cyclic. It’s not until somebody takes the tail of the tail<br />
of cyclic that the recursive reference is expanded, and aga<strong>in</strong> it expands only one element at a time,<br />
allow<strong>in</strong>g for an <strong>in</strong>f<strong>in</strong>ite, cyclic stream.<br />
Note that the cyclic stream is reus<strong>in</strong>g its own structure. cyclic.tail.tail is not a new stream<br />
that looks like cyclic. It really is the same object as cyclic <strong>in</strong> every sense:<br />
scala> cyclic.tail.tail eq cyclic<br />
res0: Boolean = true<br />
This technique is sometimes called “Ty<strong>in</strong>g the Knot”. For more <strong>in</strong>formation see the Haskell.org<br />
article⁷¹.<br />
However, be careful of creat<strong>in</strong>g such structures us<strong>in</strong>g the Scala standard library’s Stream. They can<br />
be quite fragile. The reason is that scala.Stream is is strict <strong>in</strong> the head element and it will also<br />
memoize⁷² the computed contents, which can lead to memory leaks.<br />
Stream.apply<br />
Be careful us<strong>in</strong>g Stream.apply, both <strong>in</strong> the standard library and <strong>in</strong> the exercises: they are constructed<br />
us<strong>in</strong>g repeated parameters, which are always strict. This means that e.g.<br />
Stream({pr<strong>in</strong>tln("One"); 1}, {pr<strong>in</strong>tln("Two"); 2}, {pr<strong>in</strong>tln("Three"); 3})<br />
will immediately pr<strong>in</strong>t One, Two, Three. Although the Stream will be constructed lazily, the contents<br />
have already been evaluated.<br />
For truly lazily constructed Streams you can always resort to #:: (which still evaluates the head<br />
value strictly!) or nested cons(..,cons(..,..)) operators <strong>in</strong> the exercises.<br />
Notes on chapter 6: Purely functional state<br />
State <strong>in</strong> Scalaz<br />
The Scalaz library⁷³ supplies a State data type⁷⁴ that is a specialization of a more general type<br />
IndexedStateT⁷⁵, where State[S,A] = IndexedStateT[Id, S, S, A] and Id[A] = A.<br />
⁷¹http://www.haskell.org/haskellwiki/Ty<strong>in</strong>g_the_Knot<br />
⁷²http://en.wikipedia.org/wiki/Memoization<br />
⁷³http://github.com/scalaz/scalaz<br />
⁷⁴http://docs.typelevel.org/api/scalaz/stable/7.1.0-M3/doc/#scalaz.package\protect\char”0024\relax\protect\char”0024\relaxState\protect\<br />
char”0024\relax<br />
⁷⁵http://docs.typelevel.org/api/scalaz/stable/7.1.0-M3/doc/#scalaz.IndexedStateT