专栏原创出处: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)
}