Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
306 views
in Technique[技术] by (71.8m points)

recursion - Scala unit type, Fibonacci recusive depth function

So I want to write a Fibonacci function in scala that outputs a tree like so:

fib(3)
| fib(2)
| | fib(1)
| | = 1
| | fib(0)
| | = 0
| = 1
| fib(1)
| = 1
= 2

and my current code is as follows:

 var depth: Int = 0
  def depthFibonacci(n:Int, depth: Int): Int={
    def fibonnaciTailRec(t: Int,i: Int, j: Int): Int = {
      println(("| " * depth) + "fib(" + t + ")")
      if (t==0) {
        println(("| " * depth) + "=" + j)
        return j
      }
      else if (t==1) {
        println (("| " * depth) + "=" + i)
        return i
      }
      else {
        depthFibonacci(t-1,depth+1) + depthFibonacci(t-2,depth+1)
      }
    }
    fibonnaciTailRec(n,1,0)
  }
  println(depthFibonacci(3,depth))

which, when run, looks like:

fib(3)
| fib(2)
| | fib(1)
| | =1
| | fib(0)
| | =0
| fib(1)
| =1
2

As you can see there is no "= " at the end of any fibonacci numbers greater than 1, and I am unable to implement this in my depthFibonacci function or else the type becomes Unit. How can I fix this?

question from:https://stackoverflow.com/questions/65862233/scala-unit-type-fibonacci-recusive-depth-function

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Is this close to what you're after?

def depthFib(n:Int, prefix:String = ""):Int = {
  println(s"${prefix}fib($n)")
  val res = n match {
    case x if x < 1 => 0
    case 1 => 1
    case _ => depthFib(n-1, prefix+"| ") +
              depthFib(n-2, prefix+"| ")
  }
  println(s"$prefix= $res")
  res
}

usage:

depthFib(3)

Stack Safe

As it turns out, we can achieve tail call elimination, even without proper tail call recursion, by using TailCalls from the standard library.

We start with the Fibonacci implementation as found on the ScalaDocs page and add 3 strategically placed println() statements.

import scala.util.control.TailCalls._

def fib(n: Int, deep:Int=0): TailRec[Int] = {
  println(s"${"| "*deep}fib($n)")
  if (n < 2) {
    println(s"${"| "*deep}= $n")
    done(n)
  } else for {
    x <- tailcall(fib(n-1, deep+1))
    y <- tailcall(fib(n-2, deep+1))
  } yield {
    println(s"${"| "*deep}= ${x+y}")
    x + y
  }
}

usage:

fib(3).result

But things aren't quite what they seem.

val f3 = fib(3)  // fib(3)
println("Wha?")  // Wha?
f3.result        // | fib(2)
                 // | | fib(1)
                 // | | = 1
                 // | | fib(0)
                 // | | = 0
                 // | = 1
                 // | fib(1)
                 // | = 1
                 // = 2

Thus are the dangers of relying on side effects for your results.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...