Guest User

State-Threading Example

a guest
Mar 27th, 2013
33
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Scala 1.96 KB | None | 0 0
  1.  
  2. /**
  3.  * Not a super great example, but here is `fib` using state-threading. You can
  4.  * use this same technique for `pascal` or any function you'd like to memoize.
  5.  * If you continue with FP you will learn how to do this with the State monad,
  6.  * (which removes most of the clutter) and the Free monad (which allows you to
  7.  * use general recursion without consuming stack).
  8.  */
  9. object Fib extends App {
  10.  
  11.   /**
  12.    * Calculate the nth Fibonacci number using a recursive algorithm. Note that
  13.    * this will run out of stack space for large values of `n` (around 6000 for
  14.    * me, but it will depend on VM settings.
  15.    */
  16.   def fib(n: Int): BigInt = {
  17.  
  18.     // A type alias is just a nickname. Our memo is an immutable map.
  19.     type Memo = Map[Int, BigInt]
  20.  
  21.     // The actual implementation threads our state, so it consumes an initial
  22.     // memo and returns the answer along with a [possibly new] memo.
  23.     def fib0(n: Int, m: Memo): (Memo, BigInt) =
  24.       if (n < 3) (m, BigInt(1)) // Our base case
  25.       else m.get(n) match {
  26.         case Some(a) => (m, a)  // Answer is already known
  27.         case None =>            // Need to calculate
  28.           val (mx, a) = {      
  29.             val (m0, a0) = fib0(n - 2, m)  // Note the data flow from here
  30.             val (m1, a1) = fib0(n - 1, m0) // ... to here
  31.             (m1, a0 + a1)                  // ... to here
  32.           }
  33.           (mx + (n -> a), a)    // A new memo, and our answer
  34.       }
  35.  
  36.     // Delegate to `fib0` with an initial empty memo, and then throw the memo
  37.     // away when we get our answer back. We could also return the memo as part
  38.     // of the public API so it could be used again later; here we rebuild it
  39.     // each time someone calls the top-level `fib`.
  40.     require(n > 0, "fib(n) is defined only for positive n")
  41.     fib0(n, Map())._2
  42.  
  43.   }
  44.  
  45.   // Calculate a rather large number, then print it out in chunks.
  46.   val big = fib(2500)
  47.   println(big.toString.grouped(80).mkString("\n"))
  48.  
  49. }
Advertisement
Add Comment
Please, Sign In to add comment