If you're interested in functional programming, you might also want to checkout my second blog which i'm actively working on!!

Tuesday, July 16, 2013

Scala Streams demo

package streams
import scala.util.Random
/**
* The class Stream implements lazy lists where elements are only evaluated when they are needed.
* The Stream class also employs memoization such that previously computed values are converted
* from Stream elements to concrete values of type A.
*
* So a Stream needs an initial object and a function to compute the rest of the objects
*/
object StreamDemo {
/**
* a stream of all positive integers
*/
def naturalnumbers: Stream[Int] = Stream.from(1)
/**
* A stream of factorials. There are multiple ways to compute this stream but I particularly like
* this implementation as it maps another stream to the desired stream. Let this one sink in for a bit,
* it took me more than 1 minute to come up with this solution :)
*
*/
def factorials: Stream[Int] = 1 #:: Stream.from(2).map((x:Int) => x * factorials(x-2))
/**
factorials(0) returns first element which is 1 (not lazy evaluated)
next starts our Stream.from(2) --> {value} which we map to x * factorials(x-2)
The reason why it has to be factorials(x-2) is because our stream starts at 2 and factorials(2-2)
returns the first factorial number.
factorials(1) returns {2} * factorials(2-2) = {2} * 1 = 2
factorials(2) returns {3} * factorials(3-2) = {3} * 2 = 6
factorials(3) returns {4} * factorials(4-2) = {4} * 6 = 24
**/
sealed trait CoinFlip {
val outcome: String
override def toString = outcome
}
object Head extends { val outcome = "HEAD" } with CoinFlip
object Tail extends { val outcome = "TAIL" } with CoinFlip
val outcomes = List(Head, Tail)
def flip: CoinFlip = Random.shuffle(outcomes).apply(0)
def coinflips: Stream[CoinFlip] = flip #:: coinflips
def main(args: Array[String]): Unit = {
println(naturalnumbers.take(5).mkString("first 5 natural numbers: [", ",", "]"))
println(factorials.take(5).mkString("first 5 factorial numbers: [", ",", "]"))
println(coinflips.take(10).mkString("first 10 coinflips : [", ",", "]"))
}
/**
* This will print:
* first 5 natural numbers: [1,2,3,4,5]
* first 5 factorial numbers: [1,2,6,24,120]
* first 10 coinflips : [TAIL,TAIL,HEAD,TAIL,HEAD,TAIL,HEAD,TAIL,TAIL,TAIL]
*/
}
view raw gistfile1.scala hosted with ❤ by GitHub

2 comments:

  1. hello
    I'm very interested by streams and the different ways to construct them, but I can't understand why in "factorials" the "recursive" call is with the argument x-2 and not x-1.
    I have tested it and with x-1 there is a stack overflow...
    can you explain me this mistery?

    ReplyDelete
  2. I updated the gist with an explanation.

    ReplyDelete