This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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] | |
*/ | |
} | |
hello
ReplyDeleteI'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?
I updated the gist with an explanation.
ReplyDelete