Scala的函数进阶

73 阅读4分钟

1.函数的字面量语法

2.把函数当做参数

3.部分应用函数

(一)函数的字面量语法

字面量函数就是切换一个角度去理解函数,把函数看做一种特殊的数据类型。

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

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

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

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

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

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

object Main {
    /*
    * 函数字面量
    * 另一种定义函数的方式
    */
    
    // 方式一:使用def定义(传统方法)
    def getSum(x: Int, y: Int): Int = {
        x + y
    }
    
    // 方式二:使用函数字面量
    val getSum1 = (x: Int, y: Int) => {
        x + y
    }
    
    def main(args: Array[String]): Unit = {
        println(getSum(10, 20))     // 输出:30
        println(getSum1(10, 20))    // 输出:30
    }
}

简化后代码

object Main {
    /*
    * 函数字面量的简化写法
    * 1. 代码只有一句,省略 { }
    * 2. _ 占位符来替换形参
    */
    
    // 完整写法
    val getSum = (x: Int, y: Int) => {
        x + y
    }

    // 省略 {}
    val getSum1 = (x: Int, y: Int) => x + y

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

    // 使用 _ 来代替形参
    val getSum3: (Int, Int) => Int = _ + _

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

Scala中的函数字面量 (参数) => { 函数体 } 体现了函数式编程的核心思想——函数是一等公民,可以像其他值一样被创建、传递和使用。这使得Scala能够很好地支持函数式编程范式,同时保持与面向对象编程的兼容性。

核心概念总结:

1.函数字面量(参数) => { 函数体 } 是一个表达式,它产生一个函数值

2.一等公民:函数可以作为值被赋值、传递、返回

3.类型安全:Scala是静态类型语言,函数字面量也有明确的类型

4.语法糖:Scala提供了很多简化写法,让函数式编程更简洁

(二)把函数作为参数

某个函数的参数是函数

定义一个接收函数作为参数的函数def a(f:()=>Unit)={},其中函数的类型()=>Unit部分()为函数的参数,Unit为函数的返回值。通过定义字面量传递值时,字面量必须和函数的类型匹配。

核心概念:

  1. 函数类型(Int, Int) => Int 表示接受两个Int参数,返回Int的函数类型
  2. 高阶函数operate 函数接受另一个函数作为参数
  3. 函数作为一等公民:函数可以像其他值一样被传递和使用
object Main {
    /*
    * 把一个函数当做参数传递给另一个函数
    */
    
    // 定义两个字面量函数。(Int, Int)=> Int 看成一种数据类型
    val f1: (Int, Int) => Int = _ + _
    // val a:Int = 1
    
    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) = 30
        println(test(f2, 10, 20))  // 相当于 f2(10, 20) = 200
    }
}

这个例子完美展示了Scala函数式编程的核心特性:函数可以作为参数传递,这使得代码更加灵活和可复用。

(三)Scala部分应用函数

什么是部分应用函数?

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

  • 部分应用:只提供函数的部分参数,返回一个需要剩余参数的新函数
  • 延迟执行:可以先"固定"某些参数,稍后提供剩余参数

关键点:

  1. 语法:函数名(固定参数, _: 类型, ...)
  2. 返回值:返回一个新的函数,需要剩余参数
  3. 类型安全:Scala会检查类型匹配
  4. 灵活性:可以固定任意位置的参数
object Main {
    /*
    * 部分应用函数
    * 如果一个函数需要3个参数,而我们只给了2个参数,会怎么样?
    */
    
    def getSum(a: Int, b: Int, c: Int): Int = {
        a + b + c
    }
    
    def main(args: Array[String]): Unit = {
        // 正常调用
        println(getSum(10, 20, 30))  // 输出:60
        
        // 部分应用函数:只提供前两个参数,第三个用占位符
        val t = getSum(10, 20, _: Int)  // t 就是部分应用函数!
        val t1 = getSum(_, 20, _: Int)  // t1 也是部分应用函数!
        
        println(t(50))   // 输出:80 (10 + 20 + 50)
        println(t1(10, 30))  // 输出:60 (10 + 20 + 30)
    }
}