您当前的位置: 首页 > 

梁云亮

暂无认证

  • 1浏览

    0关注

    1211博文

    0收益

  • 0浏览

    0点赞

    0打赏

    0留言

私信
关注
热门博文

函数式编程

梁云亮 发布时间:2020-04-14 12:07:06 ,浏览量:1

简介

函数式编程把函数当做一等公民,充分利用函数,支持函数的多种使用方式。 在 Scala 当中,函数是一等公民,像变量一样,既可以将函数作为函数的参数使用,也可以将函数赋值给一个变量。 Scala中函数的创建不用依赖于类或者对象

定义函数

语法: val 函数名: 参数列表 => 函数返回值类型 = 函数体 // 不能指定形参 或 val 函数名 = 参数列表 => 函数体 // 可以指定形参 或 val 函数名 = new Function2[参数列表]{ def apply(参数列表):返回值类型=函数体 //返回值类型为参数列表中最后一个类型 } 或 (参数列表) => 函数体

注:声明中的参数列表可以只指定类型不指定参数名,在函数体中通过_表示参数名

示例:函数的定义

object ScalaDemo {
  val f1 = (a: Int, b: Int) => a + b  //没有指定返回值类型
  val f2 = ((a: Int, b: Int) => a + b)
  val f3 = (_: Int) + (_: Int)
  
  val f4: (Int, Int) => Int = (_ + _)  //指定返回值类型
  val f5: (Int, Int) => Int = (x, y) => x + y
  val f6: ((Int, Int) => Int) = { 
    (x, y) => x + y 
  }
  
  val f7 = new Function2[Int, Int, Int] {
    def apply(x: Int, y: Int): Int = if (x  42  //  无参函数
  println(getTheAnswer())
}
定义方法

语法规则: def 方法名 ([参数名:参数类型], …)[[:返回值类型] =] { 语句… //完成某个功能 return 返回值 }

方法的返回值类型可以不写,编译器可以自动推断出来,但是对于递归函数,必须指定返回类型。

示例:

object ScalaDemo{
  def add1(x:Int,y:Int):Int = x+y
  //也可以定义成
  def add2(x:Int,y:Int)=x+y
  //也可以定义成
  def add3(x:Int,y:Int){   //不指定返回值且没有行号,一定要用大括号将方法体括起来
    x+y
  }
}

示例:

object FunDemo {
  def main(args: Array[String]): Unit = {   //Unit:没有返回值
    println(sum(1, 2, '-'))
  }
  //如果函数返回的类型是多种的,则推荐使用类型推导
  def sum(n1: Int, n2: Int, op: Char) = {
    if (op == '+') {
      n1 + n2
    } else if (op == '-') {
      n1 - n2
    } else {
      null
    }
  }
}
方法和函数的区别
  • 在 scala 中,方法和函数几乎可以等同,Scala中的方法就是函数,只是函数的使用方式更加的灵活多样。
  • 方法与函数本质上一样,但是形式上略有差异。
  • 方法和函数的定义的语法不同:用def 语句定义方法,val语句可以定义函数
  • 方法一般定义在某个类、特质、或者object中
将方法转换成函数

把方法作为参数传给一个方法或者函数的时候,方法自动被转换为函数。 将方法转换成函数的方式是:使用下划线_

示例:

object ScalaDemo {
  def f1(n: Int): Int = { //方法
    n * 2
  }
  def main(args: Array[String]): Unit = {
    val f2 = f1 _ //将方法转换为函数
    println(f2(10)) // 调用函数 20
  }
}
递归函数

示例:请使用递归的方式,求出斐波那契数 1,1,2,3,5,8,13…第n项的值是多少?

object FunDemo {
  def main(args: Array[String]): Unit = {
    println(fbn(6))
  }
  def fbn(n: Int): Int = {
    if (n == 1 || n == 2) {
      1
    } else {
      fbn(n - 1) + fbn(n - 2)
    }
  }
}

示例:已知 f(1)=3; f(n) = 2*f(n-1)+1; 请使用递归的思想编程,求出 f(n)的值

object FunDemo {
  def main(args: Array[String]): Unit = {
    println(f(6))
  }
  def f(n: Int): Int = {
    if (n == 1) {
      3
    } else {
      2 * f(n - 1) + 1
    }
  }
}

5.6. 惰性函数 惰性计算(尽可能延迟表达式求值)是许多函数式编程语言的特性。Java 并没有为惰性提供原生支持,Scala 提供了。 当函数返回值被声明为 lazy 时,函数的执行将被推迟,直到我们首次对其取值,函数才会执行。这种函数我们称之为惰性函数。惰性在 Java 的某些框架代码中被称之为懒加载(延迟加载)。 注意:  lazy 不能修饰 var 类型的变量  在调用函数时,加了lazy会导致函数的执行被推迟;  在声明一个变量时,如果给声明了 lazy,那么变量值得分配也会推迟。比如:lazy val i = 10。

示例: object FunDemo { def main(args: Array[String]): Unit = { lazy val res = sum(1,2) println(“res=” + res) //当需要使用到 res 时,就会真正的开始计算 } def sum(n1:Int,n2:Int): Int = { n1 + n2 } }

高阶函数

高阶函数是指使用其他函数作为参数、或者返回一个函数作为结果的函数。

示例:函数作为方法的参数–模拟命令设计模式

object MethodAndFunctionDemo {
  def m1(f: (Int, Int) => Int): Int = { //函数作为方法的参数
    f(2, 6)
  }
  //定义一个求和函数f1,参数是两个Int类型,返回值是一个Int类型
  val f1 = (x: Int, y: Int) => x + y
  //再定义一个求积函数f2
  val f2 = (m: Int, n: Int) => m * n

  def main(args: Array[String]): Unit = {  //main方法
    //调用m1方法,并传入f1函数
    val r1 = m1(f1)
    println(r1)
    //调用m1方法,并传入f2函数
    val r2 = m1(f2)
    println(r2)
  }
}

示例:函数作为方法的返回值

object ScalaDemo {
  def urlBuilder(ssl: Boolean, domainName: String): (String, String) => String = {
    val schema = if (ssl) {
      "https://"
    } else {
      "http://"
    }
    (endpoint: String, query: String) => s"$schema$domainName/$endpoint?$query"
  }

  def main(args: Array[String]): Unit = {
    val domainName = "www.example.com"
    def getURL = urlBuilder(ssl = true, domainName)
    val endpoint = "users"
    val query = "id=1"
    val url = getURL(endpoint, query)
    println(url)
  }
}
关注
打赏
1665409997
查看更多评论
立即登录/注册

微信扫码登录

0.3504s