scala中的函数进阶

81 阅读5分钟

Scala 函数进阶涵盖高阶函数、闭包、柯里化等核心概念。高阶函数可将函数作为参数或返回值,如 map 方法接收匿名函数处理集合。闭包允许函数捕获外部作用域变量,延长其生命周期,例如在循环中生成带状态的函数。柯里化将多参数函数转为单参数函数链,通过 def add(x: Int)(y: Int) = x + y 形式实现,便于参数分步传递和类型推断。

此外,部分应用函数通过下划线固定部分参数生成新函数,如 val add5 = add(5)_。隐式函数可自动转换类型,增强代码灵活性。函数组合(compose/andThen)能将多个函数串联执行,提升代码复用性。这些特性使 Scala 函数式编程更灵活,支持模块化和简洁表达复杂逻辑。

1.函数的字面量语法

除了使用def之外的,另一种定义函数的方式

语法:

var 变量 = (参数列表)=>{方法体}

它省略了def,函数名以及函数的返回值类型。

代码如下:

object base44 {
/*
* 函数字面量
* 另一种定义函数的方式
* */

  //定义函数的方式一:def
  def getSum(x:Int,y:Int):Int = {
    x + y
  }

  def getSum1= (x:Int,y:Int) =>{
    x + y
  }

  def main(args: Array[String]): Unit = {
    println(getSum(10,20))
    println(getSum1(10,20))

  }
}

运行结果如下:

Snipaste_2025-10-21_08-34-16.png

// 定义  
val sum1 = (x:Int, y:Int)=>{x+y}  
// 调用  
var s = sum1(10,34)

简化写法

Scala的函数字面量的简化方式有两种方式:

第一种方式为:_(占位符)。如果函数中的参数在方法体中只使用了一次,可以用_替换。

第二种方式为:只有一个表达式时,可以省略括号。

object base45 {
  /*
   *函数字面量的简化写法
   * 1.代码只有一句,省略{}
   * 2.—占位符表示形参
   */
  //
  val getSum = (x:Int , y:Int) => {
    x + y
  }
  //省略{}
  val getSum1 = (x:Int , y:Int) => x + y

  //使用_代替形参
  val getSum2 = (_:Int) + (_:Int)

  //使用_代替形参。(Int,Int)=>Int 就是getSum3的类型
  val getSum3:(Int,Int) => Int = _ + _

  def main(args: Array[String]): Unit = {
    println(getSum(10,20))
    println(getSum1(10,20))
    println(getSum2(10,20))
    println(getSum3(10,20))
  }
}

2.函数作为参数

某个函数的参数是函数

在 Scala 中,允许函数的参数是另一个函数(这类函数称为高阶函数),这是函数式编程的核心特性之一。这种设计让代码更灵活、模块化,能轻松实现逻辑复用和行为定制。以下结合具体示例详细解释:

A. 核心概念

  • 函数类型:函数在 Scala 中是 “一等公民”,可以像变量一样传递。函数的类型由参数类型返回值类型共同定义,格式为:(参数类型1, 参数类型2, ...) => 返回值类型。例如:(Int, Int) => Int 表示 “接收两个 Int 参数、返回 Int 的函数”。
  • 高阶函数:接收函数作为参数,或返回函数作为结果的函数。本文重点讨论 “参数是函数” 的情况。

B. 示例解析

object base46 {
  /*
    把一个函数 当参数 传递给另一个函数
   */

  // 定义两个字面量函数。(Int, Int) => Int 看成一种数据类型
  val f1: (Int, Int) => Int = _ + _

  val f2: (Int, Int) => Int = _ * _

  // 定义一个函数,它有三个参数
  // 参数1:类型是 (Int,Int)=>Int 。它表示这里需要一个函数
  def test(fn: (Int, Int) => Int, x: Int, y: Int): Int = {
    fn(x, y)
  }

  def main(args: Array[String]): Unit = {
    println(test(f1, 10, 20) + " === " + f1(10, 20))
    println(test(f2, 10, 20))
  }
}

C. 关键细节

  • 函数参数的声明:在高阶函数的参数列表中,需明确指定函数参数的类型(如 func: (Int, Int) => Int),表示 “此处需要一个符合该类型的函数”。

  • 函数的传递方式

    • 可以传递已定义的函数变量(如示例中的 addmultiply)。
    • 可以直接传递匿名函数(如 (a, b) => a - b),简化代码。
  • 函数的调用:在高阶函数内部,通过参数名(如 func)调用传入的函数,并传入所需参数(如 func(x, y))。

D. 应用场景

  • 逻辑复用:将通用逻辑(如遍历集合)封装为高阶函数,通过传入不同的处理函数实现多样化需求(例如 List.map(f) 中,map 是高阶函数,f 是处理每个元素的函数)。
  • 行为定制:允许调用者动态指定函数的核心逻辑(如排序算法中,通过传入比较函数定制排序规则)。
  • 简化代码:避免重复编写相似逻辑,用匿名函数快速传递简单逻辑。

通过函数作为参数,Scala 实现了 “用代码定义代码的行为”,大幅提升了代码的灵活性和表达力,是函数式编程思想的典型体现。

3.Scala部分应用函数

如果一个函数包含多个参数,对该函数传递部分参数使得这个函数返回一个函数,那么这种函数叫做部分应用函数

代码如下:

object base47 {
 def getSum(a: Int, b: Int, c: Int): Int = {
   a + b + c
 }

 def main(args: Array[String]): Unit = {
   println(getSum(10, 20, 30))

   val t = getSum(10, 20, _) // 部分应用函数
   val t1 = getSum(20, 20, _) // 部分应用函数

   println(t(30))
   println(t1(50))
 }
}