函数式编程中没有循环语句,所有循环都是通过递归来实现
def factorial(n: Int): Int = if (n <= 0) 1 else n * factorial(n-1)
容易堆栈溢出,优化==>
@annotation.tailrec def factorial(n:Int, m:Int): Int= if (n <= 0) m else factorial(n-1, m*n) factorial(5,1)
仅保存当前最新
递归函数:n!
def factorial(n: Int): Int =
if (n <= 0) 1
else n * factorial(n - 1)
尾递归函数:对递归函数的优化
def factorial(n: Int, m: Int): Int =
if (n <= 0) m
else factorial(n - 1, m * n) //> factorial: (n: Int, m: Int)Int
factorial(5, 1) //> res0: Int = 120
factorial(5,1)的计算逻辑:
(5,1)=>(5-1,5*1)=>(4-1,5*1*4)=>(3-1,5*1*4*3)=>(2-1,5*1*4*3*2)=>(1-1,5*1*4*3*2*1)=>5*1*4*3*2*1
注:scala中也有while,do ... while,for循环语法,但其运行逻辑不符合函数式编程思想,所以不建议使用,而建议使用递归实现循环
递归函数基于栈
尾递归中所有递归形式的调用都出现在末尾,当编译器检测到一个函数调用尾递归时,就覆盖当前的活动记录而不是在栈中创建一个新的
@annotation.tailrec 告知scala,对此为函数进行尾递归优化
@ annotation. tailrec
def factorial(n: Int,m: Int): Int=
if(n<=e)m
else factorial(n-1,m*n)
// @ annotation. tailrec 是尾递归优化必须
factorial(5,1)
尾递归函数
尾递归函数(Tail Recursive Function)中所有递归形式的调用都出现在函数的未尾。
当编译器检测到一个函数调用是尾递归的时候,它就覆盖当前的活动记录而不是在栈中去创建一个新的。
@。。。。//告诉Scala编译器,下面是个递归,要进行尾递归优化
这样的好处在于,只需要开辟一个栈和一个多的变量m
因为m*n代表的m一直在更新。
现代计算机一般通过堆栈来调用函数,这样递归层数比较多容易造成栈的溢出。
@annotation.tailrec 告诉scala编译器进行尾递归优化
尾递归函数
递归函数实现n!
@annotation.tailrec告诉编译器进行尾递归的优化
尾递归函数
简单理解为: fatorial(1,1*5*4*3*2*1) 尾递归最后一步调用后m就为上面那一堆相乘,结果明显为:1*5*4*3*2*1
尾递归函数(Tail Recursive Function)中所有递归形式的调用都出现在函数的末尾。
当编译器检测到一个函数调用是尾递归的时候,它就覆盖当前的活动记录而不是在栈中去创建一个新的