Scala把函数当参数传递

82 阅读3分钟

1. 两种函数定义方式对比

(1)方式一:def 定义常规函数

def getSum(x: Int, y: Int): Int = {
  x + y
}
  • 这是 Scala 中定义函数的传统方式,使用def关键字声明。

  • 结构:def 函数名(参数列表: 参数类型): 返回值类型 = { 函数体 }

    • getSum是函数名
    • (x: Int, y: Int)是参数列表(两个Int类型的参数xy
    • : Int指定返回值类型为整数
    • 函数体x + y表示返回xy的和

(2)方式二:函数字面量(Lambda 表达式)

val getSum1 = (x: Int, y: Int) => {
  x + y
}
  • 这是 Scala 中更简洁的函数定义方式,本质是将一个函数作为值赋值给变量(这里是val常量)。

  • 结构:val 变量名 = (参数列表: 参数类型) => { 函数体 }

    • getSum1是变量名(存储函数的常量)
    • (x: Int, y: Int)是参数列表(同方式一)
    • =>是 Lambda 运算符,左边是参数,右边是函数体
    • 函数体x + y同样表示返回xy的和
    • 无需显式声明返回值类型(Scala 会自动推断为Int

2. 主方法 main 的调用与输出

def main(arrgs: Array[String]): Unit = {
  println(getSum1(10, 20))  // 调用函数字面量getSum1,输出30
  println(getSum(10, 20))   // 调用常规函数getSum,输出30
}
  • 两种函数的调用方式完全相同:通过函数名(参数)调用。
  • 无论是getSumdef定义)还是getSum1(函数字面量),传入1020后,都会返回30,因此两次打印的结果都是30

核心区别与应用场景

  • def定义的函数:是 “方法” 级别的定义,更适合作为独立的功能模块,支持递归(自己调用自己)等复杂逻辑。
  • 函数字面量:本质是 “函数值”,可以像普通变量一样传递、赋值(例如作为参数传给其他函数),更适合简洁的逻辑或函数式编程中的 “高阶函数” 场景(如集合的mapfilter等操作)。

主体代码如下:

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

//定义函数方式一:def
def getSum(x:Int,y:Int):Int = {
  x + y
}
//定义函数方式二:字面量
val getSum1 = (x:Int,y:Int) => {
  x + y
}

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

这段代码的核心是展示 Scala 的灵活性:既支持传统的函数定义,也支持更简洁的函数字面量,后者是函数式编程的重要特性。

函数作为参数传递的用法

  1. 首先定义了两个函数值:

    • f1 是一个接收两个 Int 参数并返回它们之和的函数(等价于 (a,b) => a + b
    • f2 是一个接收两个 Int 参数并返回它们之积的函数(等价于 (a,b) => a * b
  2. 然后定义了一个test函数:

    • 第一个参数fn是函数类型(Int,Int)=>Int,表示它接收两个 Int 参数并返回 Int
    • 后面两个参数xy是 Int 类型
    • 函数体是调用传入的函数fn,并将xy作为参数传递给它
  3. main方法中:

    • 第一次调用test(f1,10,20),实际执行的是f1(10,20),结果为 30
    • 第二次调用test(f2,10,20),实际执行的是f2(10,20),结果为 200
//
val f1:(Int,Int) => Int =  _+_

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

//定义一个函数,他有三个参数
//参数1,类型是(Int,Int)=>Int,他表示这里需要一个函数
def test(fn: (Int,Int)=>Int, x:Int, y:Int) ={
  fn(x,y)
}
def main(arrgs:Array[String]):Unit = {
  println( test(f1,10,20) )
  println( test(f2,10,20) )
}