专栏原创出处:github-源笔记文件 (opens new window)github-源码 (opens new window),欢迎 Star,转载请附上原文出处链接和本声明。

Scala 编程语言专栏系列笔记,系统性学习可访问个人复盘笔记-技术博客 Scala 编程语言 (opens new window)

# 什么是高阶函数

具有以下 2 者特点之一的 函数 或者 方法,称之为高阶函数:

  • 高阶函数的参数有可能用的是另一个函数。
  • 高阶函数的返回值有可能是一个函数。

# 示例说明

# 参数是函数的函数

scala 中的 map 是一个高阶函数,接收一个函数作为参数。

  val salaries = Seq(20000, 70000, 40000)
  val doubleSalary = (x: Int) => x * 2
  val newSalaries1 = salaries.map(doubleSalary) // doubleSalary 是一个函数,被应用在了 salaries 的每一个元素上。
  val newSalaries2 = salaries.map(x => x * 2) // 没有显示的声明参数 x 的类型,scala 可以自行推断出类型
  val newSalaries3 = salaries.map(_ * 2) // 省略参数名,使用_ 替代

# 返回值为函数的函数

urlBuilder 的返回值类型是 (String, String) => String
这意味着返回的匿名函需要两个 String 类型的参数,得到一个 String 类型的结果。

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"
}

val domainName = "www.example.com"
def getURL = urlBuilder(ssl=true, domainName)
val endpoint = "users"
val query = "id=1"
val url = getURL(endpoint, query) // "https://www.example.com/users?id=1": String

# 强制转换方法为函数

传入一个对象方法作为高阶函数的参数,Scala 编译器会将方法强制转换为一个函数。

// 编译器强制将方法 convertCtoF 转成了函数 x => convertCtoF(x)
// (注: x 是编译器生成的变量名,保证在其作用域是唯一的)
case class WeeklyWeatherForecast(temperatures: Seq[Double]) {

  private def convertCtoF(temp: Double) = temp * 1.8 + 32

  // <-- passing the method convertCtoF
  def forecastInFahrenheit: Seq[Double] = temperatures.map(convertCtoF)
}

# 高阶函数的作用

使用高阶函数的一个原因是减少冗余的代码。
可以实现复杂逻辑功能的计算。

// 未使用高阶函数,给员工计算薪资,每一种计算方式要定义一个获取薪资的方法
object SalaryRaiser {

  def smallPromotion(salaries: List[Double]): List[Double] =
    salaries.map(salary => salary * 1.1)

  def greatPromotion(salaries: List[Double]): List[Double] =
    salaries.map(salary => salary * math.log(salary))

  def hugePromotion(salaries: List[Double]): List[Double] =
    salaries.map(salary => salary * salary)
}

// 使用高阶函数,只需要定义一个获取薪资的方法,将薪资列表和计算薪资的函数作为参数传入获取薪资的方法中
object SalaryRaiser2 {

  private def promotion(salaries: List[Double],
                        promotionFunction: Double => Double): List[Double] =
    salaries.map(promotionFunction)

  def smallPromotion(salaries: List[Double]): List[Double] =
    promotion(salaries, salary => salary * 1.1)

  def bigPromotion(salaries: List[Double]): List[Double] =
    promotion(salaries, salary => salary * math.log(salary))

  def hugePromotion(salaries: List[Double]): List[Double] =
    promotion(salaries, salary => salary * salary)
}
最后修改时间: 2/17/2020, 4:43:04 AM