Scala从入门到精通02之函数

1. 函数基础

1.1. 函数基本语法

在这里插入图片描述

package com.michael.learn.day02

object FunctionBasic {

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

    // 1. define a basic function and call the function
    def f(arg: String):Unit = {
      println(arg)
    }
    f("This is a string as the para")
  }
}

1.2. 函数和方法的区别

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

package com.michael.learn.day02

object DifferrenceBetweenFuncAndMethod {

  // 1. The method can be override and overwrite
  def main(): Unit = {

  }

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

    // 2. You can declare any syntax in any syntax structure with Scala language
    import java.util.Date
    new Date()

    // 3. Function can not be override and overwrite
    def testFunction(): Unit = {
      println("No para, No return value")
    }
    testFunction()

//    def testFunction(name:String): Unit = { There is an error, cause function can not be override
//      println(name)
//    }
//    testFunction("michael test")

    // 3. You can declare nested functions in Scala language
    def testFunction02():Unit = {
      def testFunction03(name: String):Unit = {
        println("The name you just input is : " + name)
      }
      testFunction03("michael")
    }
    testFunction02()
  }
}

1.3. 函数定义

package com.michael.learn.day02

object FunctionPara {

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

    // 1. Function01: no para, no return
    def test1():Unit = {
      println("No para, No return value")
    }
    test1() // No para, No return value

    // 2. Function02: No para, return a string
    def test2(): String = {
      return "No para but return value"
    }
    println(test2()) // No para but return value

    // 3. Function03: Para, no return
    def test3(s:String): Unit = {
      println("The input string is : "+s)
    }
    test3("michael test") // The input string is : michael test

    // 4. Function04: Para, return value
    def test4(s:String): String = {
      return s
    }
    println(test4("input a string and get it back")) // input a string and get it back

    // 5. Function05: multiple paras, no return
    def test5(name:String, age:Int): Unit = {
      println(s"$name, $age")
    }
    test5("michael", 18)  // michael, 18
  }
}

1.4. 函数参数

package com.michael.learn.day02

object FunctionPara {

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

    // 1. variable parameter
    def test(str:String*):Unit = {
      println(str)
    }
    test("hello", "scala") // WrappedArray(hello, scala)
    test()                     // List()

    // 2. The variable para is usually placed last if there are more than one para in the para list
    def test2(first:String, multiple:String*):Unit = {
      println(first + ", " + multiple)
    }
    test2("first para", "second", "third") // first para, WrappedArray(second, third)

    // 3. Default value of para
    def test3(name:String = "first", age:Int = 15):Unit = {
      println(s"$name, $age")
    }
    test3("michael", 18)   // michael, 18
    test3()                            // first, 15
    test3(age=19)                      // first, 19
  }
}

1.5. 函数置简原则

函数至简原则:能省则省

1.5.1. 至简原则细节

  • return 可以省略,Scala 会使用函数体的最后一行代码作为返回值
  • 如果函数体只有一行代码,可以省略花括号
  • 返回值类型如果能够推断出来,那么可以省略(:和返回值类型一起省略)
  • 如果有 return,则不能省略返回值类型,必须指定
  • 如果函数明确声明 unit,那么即使函数体中使用 return 关键字也不起作用
  • Scala 如果期望是无返回值类型,可以省略等号
  • 如果函数无参,但是声明了参数列表,那么调用时,小括号,可加可不加
  • 如果函数没有参数列表,那么小括号可以省略,调用时小括号必须省略
  • 如果不关心名称,只关心逻辑处理,那么函数名(def)可以省略

1.5.2. 代码实例

package com.michael.learn.day02

object FunctionMinimizationPrinciple {

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

    // Standard function declare
    def f(s:String):String = {
      return s + "function return"
    }
    println(f("the standard function "))  // the standard function function return

    // 1. return can be omitted in Scala
    def f1(s:String):String = {
      s + "return is omitted"
    }
    println(f1("the function without return "))  // the function without return return is omitted

    // 2. {} can be omitted if there is only one line code
    def f2(s:String):String = s + "{} is omitted"
    println(f2("omit brace")) // omit brace{} is omitted

    // 3. : and return_type can be omitted if the return value type can be inferred
    def f3(s:String) = s + "return type is omitted"
    println(f3("omit return type")) // omit return typereturn type is omitted

    // 4. return type can not be omitted if there is a return
    def f4(s:String):String = return s + "{} is omitted"
    println(f4("Don't omit return value")) // Don't omit return value{} is omitted

    // 5. The return does not work if return type is Unit
    def f5(s:String):Unit = return s + "return does not work"
    println(f5("Use unit"))   // ()

    // 6. = can be omitted if there is no return value
    def f6() {"= is omitted"}
    println(f6()) // ()

    // 7. () can be omitted when call the func if there is no para when defined with para list
    def f7():String = {"no para"}
    println(f7()) // no para
    println(f7)   // no para

    // 8. () must be omitted when call the func if defined without para list
    def f8:String = {"no para list"}
    println(f8)       // no para list
    // println(f8())  // error

    // 9. def can be omitted if only care about logic process
    def f9 = (x:String) => {println(x + "new function define way with =>")}
    def f10(f:String => Unit) = {
      f("")
    }
    f10(f9)       // new function define way with =>
    println(f10((x:String) => println("def is omitted")))  // def is omitted
  }
}

2.函数高级

2.1. 高阶函数

package com.michael.learn.day02

object AdvancedFunction {

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

    // 1. call func
    foo()    // foo is called............

    // 2. call foo and give the return value to the variable f
    val f = foo()  // foo is called............
    println(f)     // return a string

    // 3. passing the func foo as a whole to the variable f1 is the same as passing the func foo as a whole
    val f1 = foo _
    foo() // foo is called............
    f1()  // foo is called............

    // 4. The _ can be omitted if the return type is specified
    val f2:() => String = foo
    f2()  // foo is called............

    // 5. func can be the para of another func
    def f3(foo2:(Int, Int) => Int):Int = {
      foo2(2, 4)
    }

    def add(a:Int, b:Int):Int = a + b
    println(f3(add _))
    println(f3(add))

    // 6. func can be the return value
    def foo3() = {
      def foo4() = {
        println("the inner func is called")
      }
      foo4 _
    }
    val f4 = foo3()
    f4()       // the inner func is called
    foo3()()   // the inner func is called
  }

  // define func
  def foo():String = {
    println("foo is called............")
    return "return a string"
  }
}

2.2. 匿名函数

没有名字的函数就是匿名函数。
(x:Int)=>{函数体} x:表示输入参数类型;Int:表示输入参数类型;函数体:表示具体代码逻辑

2.2.2. 匿名函数基础推导

package com.michael.learn.day02

object AnonymousFunc {

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

    // 1. anonymous func usage
    def operation(arr: Array[Int], op:Int => Int) = {
      for (elem <- arr) yield op(elem)
    }

    def op(ele:Int):Int = {
      ele + 1
    }

    val arr = operation(Array(1, 2, 3, 4), op)
    println(arr.mkString(","))   // 2,3,4,5

    // 1.1. anonymous func01
    val arr1 = operation(Array(1, 2, 3, 4), (ele:Int) => {ele+1})
    println(arr1.mkString(","))  // 2,3,4,5

    // 1.2. anonymous func02 : omit para type
    val arr2 = operation(Array(1, 2, 3, 4), (ele) => ele + 1)
    println(arr2.mkString(","))  // 2,3,4,5

    // 1.3. anonymous func03 : omit ()
    val arr3 = operation(Array(1, 2, 3, 4), ele => ele + 1)
    println(arr3.mkString(","))  // 2,3,4,5

    // 1.4. anonymous func04 : omit {}
    val arr4 = operation(Array(1, 2, 3, 4), (ele) => ele + 1)
    println(arr4.mkString(","))  // 2,3,4,5

    // 1.5. anonymous func05 : omit the argument and the following argument can be replaced by _ if the argument appears only once
    val arr5 = operation(Array(1, 2, 3, 4), _ + 1)
    println(arr5.mkString(","))  // 2,3,4,5

    // 2. anonymous func usage02
    def calculator(a:Int, b:Int, op:(Int, Int) => Int):Int = {
      op(a, b)
    }
    println(calculator(2, 3, (x:Int, y:Int) => {x + y}))   // 5
    println(calculator(2, 3, (x:Int, y:Int) => x + y))     // 5
    println(calculator(2, 3, (x, y) => x + y))             // 5
    println(calculator(2, 3, _ + _))                       // 5
  }
}

2.2.2. 匿名函数的实例

package com.michael.learn.day02

import scala.collection.mutable.ArrayBuffer

object AdvancedFuncInstance {

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

    // 1. map
    def map(arr:Array[Int], op: Int => Int) = {
      for(ele <- arr) yield op(ele)
    }

    val arr = map(Array(1, 2, 3, 4), x => x*x)
    println(arr.mkString(","))    // 1,4,9,16

    // 2. filter
    def filter(arr:Array[Int], op:Int => Boolean) = {
      var arr1:ArrayBuffer[Int] = ArrayBuffer[Int]()
      for(ele <- arr if op(ele)){
        arr1.append(ele)
      }
      arr1.toArray
    }
    val arr2 = filter(Array(1, 2, 3, 4), _ % 2 == 1)
    println(arr2.mkString(","))   // 1,3

    // 3. reduce
    def reduce(arr:Array[Int], op: (Int, Int) => Int) = {
      var init:Int = arr(0)
      for(ele <- 1 to arr.length){
        init = op(init,ele)
      }
      init
    }
    val arr3 = reduce(Array(1, 2, 3, 4), _ * _)
    println(arr3)  // 24
  }
}

2.3. 函数柯里化&闭包

闭包: 如果一个函数,访问到了它的外部(局部)变量的值,那么这个函数和他所处的环境,称为闭包
函数柯里化: 把一个参数列表的多个参数,变成多个参数列表。

package com.michael.learn.day02

object FuncClosure {

  def main(args: Array[String]): Unit = {
    // 1. closure
    def f1() = {
      var a:Int = 10
      def f2(b:Int) = {
        a + b
      }
      f2 _
    }
    //  在调用时,f1 函数执行完毕后,局部变量 a 应该随着栈空间释放掉
    // 但是在此处,变量 a 其实并没有释放,而是包含在了 f2 函数的内部,形成了闭合的效果
    val f = f1()
    println(f(3))     // 13
    println(f1()(3))  // 13

    // 2. func currying
    var c:Int = 10
    def f4()(b:Int)= {
      c + b
    }
    println(f4()(3))  // 13
  }
}

2.4. 递归

一个函数/方法在函数/方法体内又调用了本身,我们称之为递归调用

package com.michael.learn.day02

object Recursion {

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

    println(test(5))   // 120

  }

  // scala 中的递归必须声明函数返回值类型
  def test(i:Int): Int ={
    if (i == 1){
      1
    }else {
      i * test(i -1)
    }
  }
}

2.5. 控制抽象

2.5.1. 值调用:把计算后的值传递过去

2.5.2. 名调用:把代码传递过去

package com.michael.learn.day02

object ControlAbstract {

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

    // 1. call func value
    def f = () => {
      println("f is called")
      10
    }
    foo(f())

    // 2. call func name
    foo2(f())

    // 3. implement your own while loop
    var i :Int = 1
    michalWhile(i <= 10){
      println(i)
      i +=1
    }
  }

  def foo(a:Int):Unit = {
    println(a)
  }

  def foo2(a: => Int):Unit = {
    println(a)
  }

  def michalWhile(condition: => Boolean)(op: => Unit):Unit = {
    if (condition){
      op
      michalWhile(condition)(op)
    }
  }
}

2.6. 惰性加载

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

package com.michael.learn.day02

object LazyLoadFunc {

  def main(args: Array[String]): Unit = {
    lazy val res = sum(100, 3)
    println("========= separator ============")
    println("res" + res)
    
   /* console result
    ========= separator ============
    sum func is called
    res103
    */
  }

  def sum(a:Int, b:Int):Int = {
    println("sum func is called")
    a + b
  }
}

注意:lazy 不能修饰 var 类型的变量

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值