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