Scala单元类型,Fibonacci递归深度函数
Scala unit type, Fibonacci recusive depth function
所以我想在 scala 中编写一个 Fibonacci 函数来输出像这样的树:
fib(3)
| fib(2)
| | fib(1)
| | = 1
| | fib(0)
| | = 0
| = 1
| fib(1)
| = 1
= 2
而我目前的代码如下:
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))
当 运行 时,它看起来像:
fib(3)
| fib(2)
| | fib(1)
| | =1
| | fib(0)
| | =0
| fib(1)
| =1
2
如您所见,任何大于 1 的斐波那契数的末尾都没有“=”,我无法在我的 depthFibonacci 函数中实现它,否则类型将变为 Unit。我该如何解决这个问题?
这接近您想要的吗?
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
}
用法:
depthFib(3)
堆栈安全
事实证明,即使没有适当的尾调用递归,我们也可以通过使用标准库中的 TailCalls
来实现尾调用消除。
我们从 ScalaDocs page 中的斐波那契实现开始,并添加 3 个战略性放置的 println()
语句。
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
}
}
用法:
fib(3).result
但事情并不像看上去的那样。
val f3 = fib(3) // fib(3)
println("Wha?") // Wha?
f3.result // | fib(2)
// | | fib(1)
// | | = 1
// | | fib(0)
// | | = 0
// | = 1
// | fib(1)
// | = 1
// = 2
这就是依赖副作用来获得结果的危险。
所以我想在 scala 中编写一个 Fibonacci 函数来输出像这样的树:
fib(3)
| fib(2)
| | fib(1)
| | = 1
| | fib(0)
| | = 0
| = 1
| fib(1)
| = 1
= 2
而我目前的代码如下:
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))
当 运行 时,它看起来像:
fib(3)
| fib(2)
| | fib(1)
| | =1
| | fib(0)
| | =0
| fib(1)
| =1
2
如您所见,任何大于 1 的斐波那契数的末尾都没有“=”,我无法在我的 depthFibonacci 函数中实现它,否则类型将变为 Unit。我该如何解决这个问题?
这接近您想要的吗?
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
}
用法:
depthFib(3)
堆栈安全
事实证明,即使没有适当的尾调用递归,我们也可以通过使用标准库中的 TailCalls
来实现尾调用消除。
我们从 ScalaDocs page 中的斐波那契实现开始,并添加 3 个战略性放置的 println()
语句。
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
}
}
用法:
fib(3).result
但事情并不像看上去的那样。
val f3 = fib(3) // fib(3)
println("Wha?") // Wha?
f3.result // | fib(2)
// | | fib(1)
// | | = 1
// | | fib(0)
// | | = 0
// | = 1
// | fib(1)
// | = 1
// = 2
这就是依赖副作用来获得结果的危险。