Scala入门篇(三):函数式编程

1. 函数与方法区别

函数方法
定义为完成某一功能的程序语句的集合
一段子程序
类中的函数
定义位置函数可以嵌套定义
重写与重载可以
函数参数可变参数 (数据类型后面加*)
默认值参数
带名参数
可变参数与默认值参数不可同时使用
参数列表中存在多个参数,那么可变参数一般放置在最后
将有默认值的参数放置在参数列表的后面

2. 基本语法

[修饰符] def 函数名 ( 参数列表 ) [:返回值类型] = {
    函数体
}
private def test( s : String ) : Unit = {
    println(s)
}

3. 函数至简原则

原则说明
省略return关键字使用函数体的最后一行代码作为返回值
省略花括号函数体逻辑代码只有一行情况下
省略返回值类型返回值类型如果能够推断出来,那么可以省略
如果有 return,则不能省略返回值类型,必须指定
如果函数明确声明 unit,那么即使函数体中使用 return 关键字也不起作用
省略等号一般返回值类型为unit时省略
如果有 return,则不能省略返回值类型,必须指定返回值类型
如果函数明确声明 unit,那么即使函数体中使用 return 关键字也不起作用
如果函数体返回值类型声明为Unit, 但是又想省略,那么此时就必须连同等号一起省略
省略参数列表参数列表中没有声明任何的参数,那么参数列表可以省略
省略之后,调用时不能加   小括号   [即不能加参数列表]
如果函数无参,但是声明了参数列表,那么调用时,小括号,可加可不加
省略关键字def和函数名省略关键字和函数名的同时也需要将 [ : 返回值类型 ] 同时省略,将等号增加一个箭头
即 (参数列表) => { 函数体 }
匿名函数不能独立使用
object TestHighFunc {
  def main(args: Array[String]): Unit = {
//    至简原则细节
//    (1)return 可以省略,Scala 会使用函数体的最后一行代码作为返回值
    def func0( str :String ):String = {str  + "\t----func0"}
//    (2)如果函数体只有一行代码,可以省略花括号
    def func1 (str : String) : String = str + "\t----func1"
//    (3)返回值类型如果能够推断出来,那么可以省略(:和返回值类型一起省略)
    def func2 (str : String)  = str +  "\t----func2"
//    (4)如果有 return,则不能省略返回值类型,必须指定
//    def func3 (str : String)  = return str  + "\t----func1"
    def func3 (str : String) : String  = return str  + "\t----func3"
//    (5)如果函数明确声明 unit,那么即使函数体中使用 return 关键字也不起作用
    def func4 (str : String) : Unit = return  str + "\t----func4"
//    (6)Scala 如果期望是无返回值类型,可以省略等号 , 大括号不可省略(即使逻辑代码只有一行) : func6
              // 将无返回值的函数称之为过程
    def func5 (str : String) { println( str + "\t----func5")}
//    def func6 (str : String)  println( str + "\t----func6")
//    (9)如果不关心名称,只关心逻辑处理,那么函数名(def)可以省略
    var func7 = (a:Int , b : Int) => a * b
    var func8 = (a:Int , b : Int) => b % a


    println(func0("Hello Scala , High Function!!!"))
    println(func1("Hello Scala , High Function!!!"))
    println(func2("Hello Scala , High Function!!!"))
    println(func3("Hello Scala , High Function!!!"))
    println(func4("Hello Scala , High Function!!!"))
    println(func5("Hello Scala , High Function!!!"))
    println(func7(3 , 9))
    println(func8(3 , 9))

  }
}

注意

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

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

返回值为Unit时,省略等号的同时 , 大括号不可省略(即使逻辑代码只有一行)

无参函数定义时若省略参数列表,调用时无须写参数列表

4. 匿名函数

([形式参数[:参数类型],形式参数[:参数类型]...]) => {函数体}

注意

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

形式参数只有一个,则圆括号可以省略

  • 无形式参数和形式参数超过 1 的永远不能省略圆括号

匿名函数体只有一行,则大括号也可以省略

形式参数在函数体中只出现一次,则参数省略且后面参数可以用_代替

  • 第一次出现的 _ 代表形式参数列表中的第 个形式参数
  • n次出现的 _ 代表形式参数列表中的第n个形式参数

匿名函数体是一个函数,调用时只写该函数名即可

5. 高阶函数

高阶函数,其实就是将函数当成一个类型来使用,而不是当成特定的语法结构

5.1 函数可以作为值进行传递

如果将函数作为整体,而不是将执行结果赋值给变量,那么需要采用特殊符号:下划线

package ch04

object TestHighFunc2 {
  def main(args: Array[String]): Unit = {
	def func(name : String) : String = name
	var a = func _
	var b = func("6666")
	println(a)
	println(b)
  }
}
ch04.TestHighFunc2$$$Lambda$1/2065951873@5e025e70
66666

使用下划线让函数作为对象使用,因为代码中没有明确变量的类型,所以需要通过取值类推断



如果变量声明的类型为函数类型,那么可以不适用下划线让函数作为对象



5.2 函数可以作为参数进行传递

将函数作为参数传入到函数中,记得传入参数时需去掉()即 传入函数类型的值 fun 或者 fun(因为知道传入的类型为函数类型,所以可以省略)



不去掉()的话会直接执行 会将执行结果作为参数传入



5.3 函数可以作为函数返回值返回

  • 定义一个函数 func,它接收一个 Int 类型的参数,返回一个函数(记作 f1)。
  • 它返回的函数 f1,接收一个 String 类型的参数,同样返回一个函数(记作 f2)。
  • 函数 f2 接收一个 Char 类型的参数,返回一个 Boolean 的值。
  • 要求调用函数 func(0) (“”) (‘0’)得到返回值为 false,其它情况均返回 true
package ch04

object TestHighFunc2 {
  def main(args: Array[String]): Unit = {
    def func(i :Int): String => (Char => Boolean) = {
      def f1(s : String) : Char => Boolean = {
        def f2(c : Char): Boolean ={
          ! (c == '0' && s == "" && i == 0)
        }
        f2 _
      }
      f1 _
    }
    println ( func(0)("")('0') )
    println ( func(4)("")('0') )
    println ( func(0)("_")('9') )
    println ( func(4)("_")('9') )
  }
}

false
true
true
true
  • 上述程序第一步省略
package ch04

object TestHighFunc2 {
  def main(args: Array[String]): Unit = {
      def func2(i :Int): String => Char => Boolean = {
      	def f1(s : String) : Char => Boolean = {
        	c => ! (c == '0' && s == "" && i == 0)
      	}
      	f1
    }
  }
}	
  • 上述程序第二步省略
package ch04

object TestHighFunc2 {
  def main(args: Array[String]): Unit = {
      def func2(i :Int): String => Char => Boolean = {// 此处大括号亦可省略
       		s => c => ! (c == '0' && s == "" && i == 0)
      }// 此处大括号亦可省略
  }
}	

6. 柯里化&闭包

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

  • 定义一个函数 func,它接收一个 Int 类型的参数,返回一个函数(记作 f1)。
  • 它返回的函数 f1,接收一个 String 类型的参数,同样返回一个函数(记作 f2)。
  • 函数 f2 接收一个 Char 类型的参数,返回一个 Boolean 的值。
  • 要求调用函数 func(0) (“”) (‘0’)得到返回值为 false,其它情况均返回 true
package ch04

object TestHighFunc {
  def main(args: Array[String]): Unit = {
    def func(i :Int) (s : String) (c : Char): Boolean = ! (c == '0' && s == "" && i == 0)
  }
}
  • 上述程序进一步简写
package ch04

object TestHighFunc {
  def main(args: Array[String]): Unit = {
    def func(i :Int) (s : String) (c : Char) = ! (c == '0' && s == "" && i == 0)
  }
}

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

7. 递归

尾递归 实现阶乘

package ch04

import scala.annotation.tailrec

object Factorial {
  def main(args: Array[String]): Unit = {
	// 尾递归
    def fact(n :Int): Int ={
      @tailrec
      def loop( n :Int , res : Int):Int = {
        if (n == 0) return res;
        print(res + "\t")
        loop( n - 1 , res * n)
      }
      loop(n , 1)
    }

    println(fact(5))

    println("-------------------------------")
    
   
	// 朴素递归 1 
    def factorial( n :Int ): Int ={
      var a = n;
      var res = a;
      while( a != 1){
        print(res + " ")
        a -= 1;
        res *= a ;
      }
      res;
    }
    println(factorial(5))
    
	// 朴素递归 2 
    def factorial2( n :Int ): Int ={
      if ( n == 0 ) return 1;
      factorial2(n - 1) * n;
    }
    println(factorial2(5))
  }
}

8. 控制抽象

值调用:把计算后的值传递过去
名调用:把代码传递过去

个人理解 : 将一段代码传入, 该代码的类型为 => [该代码块的最后一行类型]

package ch04

object DefineWhile {
  def main(args: Array[String]): Unit = {
    var n = 10;
    while( n >= 1){
      print(n + " ");
      n -= 1;
    }
    println()
    println("---------------------------------")

    n = 10;
    def DIYWhile(condition : => Boolean , op : => Unit) : Unit = {
      if(condition) {
        op
        DIYWhile( condition, op)
      }
    }
    DIYWhile( {n >= 1} , { print(n + " "); n -= 1;})

    println()
    println("---------------------------------")

    n = 10;
    def DIYWhile2(condition : => Boolean ) : (=> Unit) => Unit= {
      def loop ( op : => Unit):Unit={
        if(condition) {
          op
          DIYWhile2( condition )(op)
        }
      }
      loop
    }
    DIYWhile2( {n >= 1} )({ print(n + " "); n -= 1;}) //第二项小括号可省略 
  }
}

10 9 8 7 6 5 4 3 2 1 
---------------------------------
10 9 8 7 6 5 4 3 2 1 
---------------------------------
10 9 8 7 6 5 4 3 2 1 
  • DIYWhile2第一次省略
package ch04

object DefineWhile {
  def main(args: Array[String]): Unit = {
 n = 10;
    def DIYWhile2(condition : => Boolean ) : (=> Unit) => Unit= {
        op => {
          if(condition) {
            op
            DIYWhile2( condition )(op)
          }
        }
    }
    DIYWhile2( n >= 1 ){ 
    	print(n + " ");
    	n -= 1;
    }
  }
}

9. 惰性加载

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

package ch04

object LazyLoad {
  def main(args: Array[String]): Unit = {
    lazy val c = sum ( 9  , 1)
    println("第一次调用println")
    println("第二次调用println: Result = " + c)
  }
  def sum ( a:Int , b :Int) = {
    println("-----sum函数调用-----")
    a + b
  }
}

第一次调用println
-----sum函数调用-----
第二次调用println: Result = 10
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值