函数进阶

72 阅读4分钟

导入学习

昨天我们学习了递归函数2,其实就是函数的基本内容一些例题,和一个递归游戏,引入教大家学习,下面我们更进一步,介绍下函数的高级使用方式。

(一)函数的字面量语法

除了使用def之外的,另一种定义函数的方式
语法:var 变量 = (参数列表)=>{方法体}
它省略了def,函数名以及函数的返回值类型。

字面量定义的一些方式👉 代码:

object day30 {
/*
* 函数字面量
* 另一种定义函数的方式
*
 */
  // 定义函数的方式一: 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(110,20))
    println(getSum1(10,20))
  }
}
  1. 简化写法

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

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

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

object day31 {
/*
* 函数字面量的简化写法
* 1,代码只有一句。省略{}
* 2,_占位符来替换形参
*
 */
  //
  def getSum(x:Int, y:Int):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))
  }
}

(二)把函数作为参数

👉语法上面准确性

某个函数的参数是函数:

object day32 {
/*
* 把一个函数,当作参数,传递给另一个函数
*
 */
  //定义两个字面量函数,(Int。Int)=>Int 看成一种数据类型
  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):Int ={
  fn(x,y)
  }


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

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

// 奶茶店1  
    var add = (x:Int, y:Int) => x + y  
    // 咖啡店1  
    var mul = (x:Int, y:Int) => x*y  
    // 定义一个函数。它的特点是:第一个参数的类型是函数!  
    // 美团  
    var op = (fn: (Int, Int)=>Int, a:Int, b:Int) => {  
      fn(a,b)  
    }  
    //    add(100, 200) // 直接去奶茶店买  
    println( op(add, 100, 200) )  
    println( op(mul, 100, 200) )

说明:add理解为直接去奶茶店购买

(三)把函数作为返回值

函数的返回值是一个函数

def main(args: Array[String]): Unit = {  
    // 函数f 的返回值就是一个函数  
    var f = (x:Int) => {  
      // println(x)  
      //      var f1 = (y:Int) => x + y  
      //      f1 // 返回值是一个函数  
      (y:Int) => x + y  
    }  
  
    var s = f(2) //  s 是一个函数  
    var res = s(10)  
    println(res)  
  }

(四)scala的函数的闭包

闭包是:一个函数连同该函数的非局部变量的一个引用环境。

函数和变量的定义要在同一个作用域,函数可以引用已经创建的变量,函数可以同值一样被传递和应用,当执行函数时该函数仍然引用着变量。

object ClosureExample2 {  
def makeAdder(adder: Int): Int => Int = {

     (x: Int) => x + adder

  }

  def main(args: Array[String]): Unit = {

    val addFive = makeAdder(5)

    val addTen = makeAdder(10)

    println(addFive(3))  // 输出 8

    println(addTen(3))   // 输出 13

  }

}

(五)函数的柯里化格式定义

定义函数的另一种格式。

柯里化的定义语法为:

def 函数名(参数列表1)(参数列表2)...(参数列表n):type={
方法体
}

代码:

// 正常定义  
def add(x:Int,y:Int)=x+y  
println(add(1,2))  
// 柯里化定义:一个参数一个括号,参数单独写

def add(x:Int)(y:Int) = x + y  
println(add(1)(2))

👉🫣🧐柯里化(Currying)是函数式编程中的一个非常重要的概念,得名于美国数学家 Haskell Curry。柯里化的基本思想是将一个接受多个参数的函数转变为一系列只接受一个参数的函数,并返回接受下一个参数的新函数。

(六)Scala部分应用函数

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

object day33 {
/*
* 部分应用
*
* 如果一个函数需要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))
    val t = getSum(10,20,_) // t就是部分应用函数
    val t1 = getSum(_,20,_) // t 就是部分应用函数

    println(t(50))
    println(t1(20,50))
  }
}

2.png