Scala函数式编程

Posted leafgood

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Scala函数式编程相关的知识,希望对你有一定的参考价值。

函数式编程

Scala也是一种函数式编程语言,其函数也能当成值来使用。Scala提供了轻量级的语法用以定义匿名函数,支持高阶函数,允许嵌套多层函数,并支持柯里化。Scala的case class及其内置的模式匹配相当于函数式编程语言中常用的代数类型。

在Scala中,存在方法和函数两个概念,方法和函数在语义上区别很细小。
Scala 中的方法跟 Java 的类似,方法是组成类的一部分。scala 中的函数则是一个完整的对象。
Scala中方法和函数在语法上区别不大,只是类中声明的函数我们叫方法,方法有重载和重写,而函数则没有。

1.普通函数编程

1.1 基本语法

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

示例

object Scala_Fun {
  def main(args: Array[String]): Unit = {
    test("hello")
  }

  /**
   * 普通函数示例
   * @param str
   */
  private def test(str:String):Unit = {
    println(str)
  }
}

1.2 函数定义

object Scala_Fun {
  def main(args: Array[String]): Unit = {
    // 无参,无返回值
    def fun1(): Unit ={
      println("无参且无返回值")
    }
    
    // 无参,有返回值
    def fun2(): String ={
      // 可以省略return
      "张三" 
    }
    
    // 有参,无返回值
    def fun3(str:String): Unit ={
      println(str)
    }
    
    // 有参,有返回值
    def fun4(str:String): String ={
      "hello:"+ str
    }
    
    // 关键字参数
  }

}

1.3 函数参数

object Scala_Fun {
  def main(args: Array[String]): Unit = {
    // 可变参数
    def fun1(names:String*): Unit ={
      println(names)
    }
    fun1("张三","李四")

    // 可变参数不能放置在参数列表的前面,一般放在参数列表的最后
    // 如果学过python,会发现传参这里跟python传参很相似
    /*    错误示范
    def fun2(names:String*, count:Int): Unit ={

    }*/
    def fun2(count:Int,names:String*): Int ={
      println(names)
      count
    }

    // 参数默认值
    def fun3(name:String, age:Int = 18): Unit ={
      println(name+ ":" + age)
    }
    
    // 命名传参
    fun3(name="张三")

  }
  
}

1.4 函数精简原则

object Scala_Fun {
  def main(args: Array[String]): Unit = {
    // Scala中函数可以进行精简,所谓是能省则省,当然前提是编译器可以自动推断
    def fun1(name:String): String ={
      return "姓名:"+name
    }

    // 1.当函数有返回值时,可以将函数体中最后一行执行的代码作为返回结果,所以可以省略return关键字
    def fun2(name:String): String ={
      "fun2:"+name
    }
    println(fun2("张三"))

    // 2.如果编译器可以推断出函数的返回值类型,返回值类型则可以省略
    def fun3(name:String)={
      "fun3:"+name
    }
    println(fun3("张三"))

    // 3.如果函数体逻辑只有一行代码,则函数体的大括号可以省略
    def fun4(name:String) = "fun4:"+name
    println(fun4("张三"))

    // 4.如果函数没有参数,调用时候,小括号可以省略
    def fun5(): String ={
      "fun5"
    }
    println(fun5)

    // 5.如果函数没有提供参数,那声明时,小括号可以省略,调用时,也不能使用小括号
    def fun6 = "fun6"
    println(fun6)

    // 6.如果函数使用Unit声明没有返回值,那函数体中的return关键字不会起作用。
  /*
    def fun7():Unit={
      return "张三"
    }*/
    // 7.函数体中如果使用return关键字,则返回值不能省略
    def fun8():String = {
      "fun8"
    }
    // 8.如果函数没有返回值,Unit又不想用,那可以同时省略等号,但保留花括号
    def fun9(){
      println("张三")
    }

    // 9.匿名函数:当只关心代码逻辑,不关心函数名时,则函数名和def关键字可以省略
    // 匿名函数规则: (参数列表) => {函数逻辑}
    val fun10 = (name:String)=>println(name)
    fun10("张三")

   }

}

2.高阶函数编程

2.1什么是高阶函数和柯里化Currying

1)数学概念

回顾下数学知识:
y=f(x) 这是最开始接触的普通函数
y=g(f(x)) 这个就是我们接触到的高阶函数

在数学和计算机科学中,高阶函数至少应当是满足下面一个条件的函数:
1)接受一个或者多个函数作为参数
2)输出一个函数

程序中我们的高阶函数也类似

2)柯里化Currying
柯里化:指的是将原来接受两个参数的函数变成新的接收一个参数的函数,新的函数返回一个以原有第二个参数为参数的函数
z = f(x, y)转换成z=f(x)(y)

2.2 函数作为值

object Scala_Fun {
  def main(args: Array[String]): Unit = {
    def fun1():String = {
        "张三"
    }
    val v1 = fun1() // 调用函数,把函数的返回结果赋值给变量v1
    val v2 = fun1 _ // 把函数作为值赋值给变量v2
    println(v1)
    println(v2)

   }

}

2.3 函数作为参数

object Scala_Fun {
  def main(args: Array[String]): Unit = {
    def fun1():String = {
        "张三"
    }

    def fun2(fun:()=>String): Unit ={
      println(fun())
    }
    fun2(fun1)

   }

}

2.4 把函数作为返回值

object Scala_Fun {
  def main(args: Array[String]): Unit = {
    def fun1():String = {
        "张三"
    }

    def fun2() = {
      fun1 _
    }
    println(fun2()())

   }

}

2.5 闭包

函数在使用外部变量时,如果外部变量失效时,会将这个变量包含到当前的函数内部,形成闭合的效果,这个就是闭包。
匿名函数本身就是一种闭包。
代码示例

object Scala_Fun {
  def main(args: Array[String]): Unit = {
    def outFun(i:Int) ={
      def inFun(j:Int) = {
        i + j
      }
      inFun _
    }
    val res = outFun(10)(10)
    println(res)
  }

}

2.6 惰性函数

惰性函数,也就是延迟加载,直到我们首次对此取值,该函数才会执行,使用lazy关键字声明其返回值时,就会形成惰性函数。
示例:

object Scala_Fun {
  def main(args: Array[String]): Unit = {
    def fun():String = {
      println("张三")
      "张三"
    }
    lazy val res = fun()
    println(res)
  }

}

2.7 函数柯里化

object Scala_Fun {
  def main(args: Array[String]): Unit = {
    // 使用柯里化方式声明函数
    def fun1(a:Int,b:Int,f:(Int,Int)=>Int):Unit = {
    }
    def fun2(a:Int)(b:Int)(f:(Int,Int)=>Int) = {
      f(a,b)
    }
    // 调用函数
    println(fun2(10)(20)(_ + _))
  }

}

学过Python的话,会发现这里的高阶函数和Python的高阶函数大同小异。

以上是关于Scala函数式编程的主要内容,如果未能解决你的问题,请参考以下文章

Scala函数式编程彻底精通

Scala基础高阶函数隐式转换AKKA编程

Scala最新书籍-《函数式编程科学之Scala实战》pdf级随书代码分享

Scala学习之函数式风格编程

2021年大数据常用语言Scala(二十):函数式编程 介绍

Scala函数编程和隐式转换