Scala基础语法(二)

                目录

                          函数与方法的区别

                          函数的定义

                          关于函数的参数

                          函数至简原则

                          函数高阶用法

                          匿名函数

                          高阶函数案例

                          函数柯里化和闭包

                          关于递归

                          自定义while循环

                          惰性加载


首先,Scala 语言是一个完全面向对象编程语言。万物皆对象。其本质与JAVA一致。其次,Scala是一个完全函数式编程的语言。万物皆函数。它的编码方式类似于函数。例如:f(x) = x

1. 函数基础语法

object FunctionDeclare {
  def main(args: Array[String]): Unit = {
    //    (1)函数 1:无参,无返回值
    def test01(): Unit = {
      println("test01: 你好,戈多!")
    }
    // 函数调用
    test01()
  }
}

1.1. 函数与方法的区别

1)核心概念

(1)为完成某一功能的程序语句的集合,称为函数。 (2)类中的函数称之方法。

2)特点

(1)Scala 语言可以在任何的语法结构中声明任何的语法 (2)函数没有重载和重写的概念;方法可以进行重载和重写 (3)Scala 中函数可以嵌套定义

1.2 函数的定义

函数的定义可以分为以下6种情况:

(1)函数 1:无参,无返回值 (2)函数 2:无参,有返回值 (3)函数 3:有参,无返回值 (4)函数 4:有参,有返回值 (5)函数 5:多参,无返回值 (6)函数 6:多参,有返回值

package com.yangmin.scala01

object FunctionDeclare {
  def main(args: Array[String]): Unit = {
    //    (1)函数 1:无参,无返回值
    def test01(): Unit = {
      println("test01: 你好,戈多!")
    }
    // 函数调用
    test01()

    //    (2)函数 2:无参,有返回值
    def test02(): String = {
      return "test01: 你好,戈多!"
    }

    val str = test02()
    println(str)

    //    (3)函数 3:有参,无返回值
    def test03(name: String): Unit = {
      println(s"test03: 你好,${name}")
    }

    test03("Nacy")


    //    (4)函数 4:有参,有返回值
    def test04(name: String): String = {
      return s"test04: 你好,${name}"
    }

    println(test04("Bob"))

    //    (5)函数 5:多参,有返回值
    def test05(name: String, age: Int): String = {
      return s"test05: 你好,${age}的${name}"
    }

    println(test05("Mike", 14))

    //    (6)函数 6:多参,无返回值
    def test06(name: String, age: Int): Unit = {
      println(s"test06: 你好,${age}岁的${name}")
    }

    test06("Tom", 14)
  }
}

 1.3 关于函数的参数

(1)可变参数 (2)如果参数列表中存在多个参数,那么可变参数一般放置在最后 (3)参数默认值,一般将有默认值的参数放置在参数列表的后面 (4)带名参数

注意:可变参数,返回时是以一个数组的形式返回

package com.yangmin.scala01

object FunctionArgs {
  def main(args: Array[String]): Unit = {
    //    (1)可变参数
    def test01(s: String*): Unit = {
      println(s)
    }

    test01("hello", "world")

    //    (2)如果参数列表中存在多个参数,那么可变参数一般放置在最后
    def test02(name: String, s: String*): Unit = {
      println(name + "会" + s)
    }

    test02("Mike", "打篮球", "打羽毛球", "踢毽子")

    //    (3)参数默认值,一般将有默认值的参数放置在参数列表的后面
    def test03(name: String,`class`: String = "三年级"): Unit = {
      println( name + "在广州就读十六小学" + `class`)
    }
    test03("Nacy","五年级")
    test03("Alice")
    //    (4)带名参数

    test03(`class` = "六年级", name = "Bob")

  }
}

 1.4 函数至简原则

(1)return 可以省略,Scala 会使用函数体的最后一行代码作为返回值

(2)如果函数体只有一行代码,可以省略花括号

(3)返回值类型如果能够推断出来,那么可以省略(:和返回值类型一起省略)

(4)如果有 return,则不能省略返回值类型,必须指定

(5)如果函数明确声明 unit,那么即使函数体中使用 return 关键字也不起作用

(6)Scala 如果期望是无返回值类型,可以省略等号

(7)如果函数无参,但是声明了参数列表,那么调用时,小括号,可加可不加

(8)如果函数没有参数列表,那么小括号可以省略,调用时小括号必须省略

(9)如果不关心名称,只关心逻辑处理,那么函数名(def)可以省略

1.5 函数高阶用法

(1)作为值进行传递

object TestFunction {
  def main(args: Array[String]): Unit = {
    //(1)调用 foo 函数,把返回值给变量 f
    //val f = foo()
    val f = foo
    println(f)
    //(2)在被调用函数 foo 后面加上 _,相当于把函数 foo 当成一个整体,
    传递给变量 f1
    val f1 = foo _
    foo()
    f1()
    //(3)如果明确变量类型,那么不使用下划线也可以将函数作为整体传递给
    变量
    var f2:()=>Int = foo
  }
  def foo():Int = {
    println("foo...")
  }
}

(2)作为参数传递

def main(args: Array[String]): Unit = {
 
     // (1)定义一个函数,函数参数还是一个函数签名;f 表示函数名称;(Int,Int)表示输入两个 Int 参数;Int 表示函数返回值
     def f1(f: (Int, Int) => Int): Int = {
     f(2, 4)
     }
     
     // (2)定义一个函数,参数和返回值类型和 f1 的输入参数一致
     def add(a: Int, b: Int): Int = a + b
 
     // (3)将 add 函数作为参数传递给 f1 函数,如果能够推断出来不是调用,_可以省略
    println(f1(add))
    println(f1(add _))
    //可以传递匿名函数
 }
}

(3)函数可以作为函数返回值返回

def main(args: Array[String]): Unit = {
 def f1() = {
     def f2() = {
     }
     f2 _
 }
 val f = f1()
 // 因为 f1 函数的返回值依然为函数,所以可以变量 f 可以作为函数继续调用
 f()
 // 上面的代码可以简化为
 f1()()
}

1.6匿名函数

定义:没有名字的函数就是匿名函数。

(x:Int)=>{函数体} x:表示输入参数类型;

Int:表示输入参数类型;函数体:表示具体代码逻辑

需求 1:传递的函数有一个参数 传递匿名函数至简原则:

(1)参数的类型可以省略,会根据形参进行自动的推导

(2)类型省略之后,发现只有一个参数,则圆括号可以省略;其他情况:没有参数和参 数超过 1 的永远不能省略圆括号。

(3)匿名函数如果只有一行,则大括号也可以省略

(4)如果参数只出现一次,则参数省略且后面参数可以用_代替

def main(args: Array[String]): Unit = {
 // (1)定义一个函数:参数包含数据和逻辑函数
 def operation(arr: Array[Int], op: Int => Int) = {
 for (elem <- arr) yield op(elem)
 }
 // (2)定义逻辑函数
 def op(ele: Int): Int = {
 ele + 1
 }
 // (3)标准函数调用
 val arr = operation(Array(1, 2, 3, 4), op)
 println(arr.mkString(","))
 // (4)采用匿名函数
 val arr1 = operation(Array(1, 2, 3, 4), (ele: Int) => {
 ele + 1
 })
println(arr1.mkString(","))
 // (4.1)参数的类型可以省略,会根据形参进行自动的推导;
 val arr2 = operation(Array(1, 2, 3, 4), (ele) => {
 ele + 1
 })
 println(arr2.mkString(","))
 // (4.2)类型省略之后,发现只有一个参数,则圆括号可以省略;其他情
况:没有参数和参数超过 1 的永远不能省略圆括号。
 val arr3 = operation(Array(1, 2, 3, 4), ele => {
 ele + 1
 })
 println(arr3.mkString(","))
 // (4.3) 匿名函数如果只有一行,则大括号也可以省略
 val arr4 = operation(Array(1, 2, 3, 4), ele => ele + 1)
 println(arr4.mkString(","))
 //(4.4)如果参数只出现一次,则参数省略且后面参数可以用_代替
 val arr5 = operation(Array(1, 2, 3, 4), _ + 1)
 println(arr5.mkString(","))
 }
}

需求2:传递的函数有两个参数


object TestFunction {
 def main(args: Array[String]): Unit = {
 def calculator(a: Int, b: Int, op: (Int, Int) => Int): Int = {
     op(a, b)
 }
 // (1)标准版
     println(calculator(2, 3, (x: Int, y: Int) => {x + y}))
 // (2)如果只有一行,则大括号也可以省略
     println(calculator(2, 3, (x: Int, y: Int) => x + y))
 // (3)参数的类型可以省略,会根据形参进行自动的推导;
     println(calculator(2, 3, (x , y) => x + y))
 // (4)如果参数只出现一次,则参数省略且后面参数可以用_代替
     println(calculator(2, 3, _ + _))
 }
}

1.7 高阶函数案例

需求:模拟 Map 映射、Filter 过滤、Reduce 聚合

import scala.collection.mutable.ArrayBuffer

object Practice02 {
  def main(args: Array[String]): Unit = {
    // 需求:模拟Map映射,Filter过滤,Reduce聚合
    // (1) Map映射
    def map(array: Array[Int], op: (Int) => Int): Array[Int] = {
      for (elem <- array) yield op(elem)
    }

    val arr0 = map(Array(1, 2, 3, 4, 5, 6), (a: Int) => {
      a * a
    })

    val arr1 = map(Array(1, 2, 3, 4, 5, 6), _ + 1)
    println(arr0.mkString(","))
    println(arr1.mkString(":"))

    //    (2)filter过滤
    def filter(arr: ArrayBuffer[Int], op: Int => Boolean) = {
      val arr2: ArrayBuffer[Int] = ArrayBuffer[Int]()
      for (elem <- arr if op(elem)) {  //或者不需要额外的空间,直接使用yiled elem 即可
        arr2.append(elem)
      }
      arr2.toArray
    }

    val arr2 = filter(ArrayBuffer(1, 2, 4, 3, 12, 53), _ % 2 == 0)
    println(arr2.mkString("-"))

    // (3) reduce聚合,所有数字相乘
    def reduce (arr:Array[Int],op:(Int,Int) => Int) ={
      var init: Int = arr(0)
      for(elem <- 1 to arr.length) {
        init = op(init,elem)
      }
      init
    }
    val arr3= reduce(Array(1, 2, 3, 4), (x, y) => x * y)
    println(arr3)

  }
}

1.8 函数柯里化和闭包

(1)定义( 闭包 是函数式编程的标配

闭包:如果一个函数,访问到了它的外部(局部)变量的值,那么这个函数和他所处的 环境,称为闭包

函数柯里化:把一个参数列表的多个参数,变成多个参数列表。

闭包和柯里化案例如下:

object ClosureAndCurrying {
  def main(args: Array[String]): Unit = {
    //    闭包的用法
    def addByFour0(a: Int, b: Int): Int = {
      a + b
    }

    println(addByFour0(1, 0))

    //    改进
    def addByFour1(): Int => Int = {
      val a = 4

      def addB(b: Int): Int = {
        a + b
      }

      addB
    }

    // 在改进
    def addByFour2(a: Int): Int => Int = {
      def addB(b: Int): Int = {
        a + b
      }

      addB
    }

    println(addByFour1()(5))
    println(addByFour2(4)(3))

    val intToInt = addByFour2(1)
    println(intToInt(1))

    //    柯里化
    def addCurrying(a: Int)(b: Int) = {
      a + b
    }

  }

}

1.9 关于递归

object Recursion {
  def main(args: Array[String]): Unit = {
    //    计算n的阶乘
    println(fac(5))
  }

  //  递归实现
  def fac(n: Int): Int = {
    if (n == 1) return 1
    return fac(n - 1) * n
  }

  //尾递归实现
  def taiFac(n: Int): Int = {
    @tailrec
    def loop(n: Int, currRes: Int): Int = {
      if (n == 0 ) return currRes
      loop(n - 1, currRes * n)
    }
    loop(n,1)
  }

}

1.10 自定义while循环

object DefineWhile {
  def main(args: Array[String]): Unit = {
//    使用递归自定义while循环,这里以代码块形式传入一个条件,然后里面定义循环
    def myWhile(condition: => Boolean): (=> Unit) => Unit = {
      def doLoop(op: => Unit): Unit = {
        if (condition) {
          op
          myWhile(condition)(op)
        }
      }

      doLoop _
    }

    var i = 10
    myWhile(i > 1) {
      println("hello" + i)
      i -= 1
    }

    //    柯里化 简化
    def simpilyMyWhile(condition: => Boolean)(op: Unit): Unit = {
      if (condition) {
        op
        simpilyMyWhile(condition)(op)
      }
    }
  }
}

1.11 惰性加载

当函数返回值被声明为 lazy 时,函数的执行将被推迟,直到我们首次对此取值,该函 数才会执行。这种函数我们称之为惰性函数。

后续继续更新。。。。。。。。。。。。。。

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小M姐姐呀~

如果对您帮助,请客观打赏点

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值