Scala尾递归

本文探讨Scala中的递归与尾递归,强调尾递归如何避免堆栈溢出问题。通过实例1展示了如何用尾递归计算阶乘,解释了`@tailrec`注解的作用。此外,还介绍了柯里化的概念,如何将多参数函数转换为单参数函数链,并在实例2中结合尾递归和柯里化计算区间函数的和。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

递归与尾递归

Scala中的循环都是通过递归(Recursive)实现的。递归的缺点是运算层层压在堆栈中,递归的层数过多时,很容易造成堆栈溢出的问题。Scala中利用尾递归(Tail Recursive Function)解决递归过程中可能导致的堆栈溢出的问题。


尾递归

所有递归形式的调用都出现在函数的末尾。当编译器检测到一个函数调用是尾递归的时候,它就覆盖当前的活动记录而不是在栈中创建一个新的。

实例1:计算n!

递归方法实现n!的代码块如下:

def factorial(n: Int): Int =
    if(n <= 0) 1
    else n * factorial(n - 1)

尾递归方法实现n!的代码块如下:

@annotation.tailrec
def factorial(n: Int, m: Int): Int =
    if( n<= 0) m
    else factorial(n - 1, m * n)

注释

@annotation.tailrec的作用是告诉编译器启动尾递归优化。参数n表示阶乘的数字,参数m表示累乘器,保存前面的递归调用的结果。m拿到的一直是过去几次累乘的结果,因此只需要一个栈保留m最新的结果,而不是需要多个栈。

def main(args: Array[String])= {
    println(factorial(4, 1))
}

输出结果为:24

柯里化

柯里化函数:把具有多个参数的函数转换为一条函数链。每个节点上是单一函数。例如:

def add(x: Int, y: Int)= x + y

等价于

def add(x: Int)(y: Int)= x + y //   柯里化语法

实例2:计算 baf(x) ∑ a b f ( x )

其中f(x)表示取区间[a, b]内的整数进行运算的函数。

def sum(f: Int => Int)(a: Int)(b: Int): Int = {

    @annotation.tailrec
    def loop(n: Int)(acc: Int): Int = {
      if(n > b) acc
      else loop(n + 1)(acc + f(n))
    }

    loop(a)(0)
  }

该例结合使用了柯里化和尾递归。参数(f:Int => Int)表示f(x)loop函数完成递归累加的功能,参数(n: Int)表示每次叠加的值,参数(acc: Int)表示累加器,保存最近一次累加的结果。

println(sum(x => x)(1)(4))
println(sum(x => x * x)(1)(4))

计算结果:

10
30

另外一种表示方法为:

val square = sum(x => x * x)_
println(square(1)(4))

其中_表示通配参数列表,sum函数可变的参数为ab。所以_表示通配参数ab
计算结果同样为:

30

详细内容请移步: scala高阶函数
https://www.imooc.com/video/11275/0

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值