Scala第十三章节(作为值的函数及匿名函数、柯里化、闭包及控制抽象以及计算器案例)

本文主要是介绍Scala第十三章节(作为值的函数及匿名函数、柯里化、闭包及控制抽象以及计算器案例),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

章节目标

  1. 掌握作为值的函数及匿名函数的用法
  2. 了解柯里化的用法
  3. 掌握闭包及控制抽象的用法
  4. 掌握计算器案例

1.高阶函数介绍

Scala 混合了面向对象和函数式的特性,在函数式编程语言中,函数是“头等公民”,它和Int、String、Class等其他 类型处于同等的地位,可以像其他类型的变量一样被传递和操作。也就是说, 如果一个函数的参数列表可以接收函数对 象 , 那么这个函数就被称之为 高阶函数(High-Order Function) .像我们之前学习过的map方法,它就可以接收一个函数,完成List的转换。

常用的高阶函数有以下几类:

  • 作为值的函数
  • 匿名函数
  • 闭包
  • 柯里化等等

2. 作为值的函数

在Scala中,函数就像和数字、字符串一样,可以将函数对象传递给一个方法。例如: 我们可以对算法进行封装,然

后将具体的动作传递给方法,这种特性很有用。

示例

需求

将一个整数列表中的每个元素转换为对应个数的小星星, 如下:

List(1, 2, 3...) => *, **, ***

步骤

  1. 创建一个函数,用于将数字装换为指定个数的小星星
  2. 创建一个列表,调用map方法
  3. 打印转换后的列表

参考代码

//案例: 演示函数可以作为 对象传递.
object ClassDemo01 {
def main(args: Array[String]): Unit = {
//需求: 定义一个列表, 记录1~10的数组, 将该数字转换成对应个数的*.
//1: * , 2: **, 3: ***...
//1. 定义一个列表, 记录1~10的数字.
val list1 = (1 to 10).toList
//2. 定义一个函数对象(函数是Scala中的头等公民), 用来将Int -> String
val func = (a:Int) => "*" * a
//3. 调用函数map, 用来转换数字.
//list1.map(这里需要一个函数)
val list2 = list1.map(func)
//4. 打印结果.
println(list2)
}
}

3. 匿名函数

概述

上述的案例,把 (num:Int) => “*” * num 这个函数赋值给了一个变量,虽然实现了指定的需求, 但是这种写法有 一些啰嗦, 我们可以通过 匿名函数 来优化它。在Scala中,没有赋值给变量的函数就是匿名函数.

示例

通过匿名函数实现, 将一个整数列表中的每个元素转换为对应个数的小星星.

参考代码

//案例: 演示 匿名函数.
object ClassDemo02 {
def main(args: Array[String]): Unit = {
//需求: 定义一个列表, 记录1~10的数组, 将该数字转换成对应个数的*.
//1: * , 2: **, 3: ***...
//1. 定义一个列表, 记录1~10的数字.
val list1 = (1 to 10).toList
//2. 通过map函数用来进行转换, 该函数内部接收一个: 匿名函数.
val list2 = list1.map((a:Int) => "*" * a)
//3. 打印结果.
println(list2)
//简写版: 通过下划线实现.
val list3 = list1.map("*" * _)
//val list4 = list1.map(_ * "*") //不能这样写, 会报错.
println(list3)
}
}

4. 柯里化

4.1 概述

在scala和spark的源代码中,大量使用到了柯里化。为了方便我们后续阅读源代码,我们需要来了解下柯里化。柯里化(Currying)是指 将原先接受多个参数的方法转换为多个只有一个参数的参数列表的过程 。如下图:
在这里插入图片描述

4.2 流程详解

在这里插入图片描述

4.3 示例

需求

定义方法, 完成两个字符串的拼接.

参考代码
//案例: 演示柯里化.
object ClassDemo03 {
//需求: 定义方法, 完成两个字符串的拼接.
//方式一: 普通写法.
def merge1(s1:String, s2:String) = s1 + s2
//方式二: 柯里化操作.
def merge2(s1:String, s2:String)(f1: (String, String) => String) = f1(s1, s2)
def main(args: Array[String]): Unit = {
//调用普通写法
println(merge1("abc", "xyz"))
//调用柯里化写法.
println(merge2("abc", "xyz")(_ + _))
println(merge2("abc", "xyz")(_.toUpperCase() + _))
}
}

5. 闭包

闭包指的是 可以访问不在当前作用域范围数据的一个函数.

格式

val y = 10
val add = (x:Int) => {
x + y
}
println(add(5)) // 结果15

注意: 柯里化就是一个闭包.

需求

定义一个函数, 用来获取两个整数的和, 通过闭包的形式实现.

参考代码

//案例: 演示闭包.
object ClassDemo04 {
def main(args: Array[String]): Unit = {
//需求: 定义一个函数, 用来获取两个整数的和.
//1. 在getSum函数外定义一个变量.
val a = 10
//2. 定义一个getSum函数, 用来获取两个整数的和.
val getSum = (b:Int) => a + b
//3. 调用函数
println(getSum(3))
}
}

6. 控制抽象

控制抽象也是函数的一种, 它可以让我们更加灵活的使用函数. 假设函数A的参数列表需要接受一个函数B, 且函数B 没有输入值也没有返回值, 那么函数A就被称之为 控制抽象 函数.

格式

val 函数A = (函数B: () => Unit) => {
//代码1
//代码2
//...
函数B()
}

需求

  1. 定义一个函数myShop, 该函数接收一个无参数无返回值的函数(假设: 函数名叫f1).
  2. 在myShop函数中调用f1函数.
  3. 调用myShop函数.

参考代码

//案例: 演示控制抽象.
object ClassDemo05 {
def main(args: Array[String]): Unit = {
//1. 定义函数
val myShop = (f1: () => Unit) => {
println("Welcome in!")
f1()
println("Thanks for coming!")
}
//2. 调用函数
myShop {
() =>
println("我想买一个笔记版电脑")
println("我想买一个平板电脑")
println("我想买一个手机")
}
}
}

7. 案例: 计算器

需求

  • 编写一个方法,用来完成两个Int类型数字的计算
  • 具体如何计算封装到函数中
  • 使用柯里化来实现上述操作

目的

考察 柯里化 相关的内容.

参考代码

//案例: 演示柯里化.
//柯里化(Currying): 将一个有多个参数的参数列表 转换成 多个只有一个参数的参数列表.
/*
示例:
方法名(数值){ //就是一个方法的调用, 只不过让方法的调用更加灵活.
函数
}
*/
object ClassDemo06 {
//需求: 定义一个方法, 用来完成两个整数的计算(例如: 加减乘除).
//方式一: 普通写法.
def add(a:Int, b:Int) = a + b
def subtract(a:Int, b:Int) = a - b
def multiply(a:Int, b:Int) = a * b
def divide(a:Int, b:Int) = a / b
//方式二: 柯里化操作.
//参数列表1: 记录要进行操作的两个数据.
//参数列表2: 记录 具体的操作(加减乘除)
def calculate(a:Int, b:Int)(func: (Int, Int) => Int) = func(a, b)
def main(args: Array[String]): Unit = {
//测试普通方法.
println(add(10, 3))
println(subtract(10, 3))
println(multiply(10, 3))
println(divide(10, 3))
println("*" * 15)
//测试柯里化方法.
// 数值 函数
println(calculate(7, 3)(_ + _))
println(calculate(7, 3)(_ - _))
println(calculate(7, 3)(_ * _))
println(calculate(7, 3)(_ / _))
}
}

这篇关于Scala第十三章节(作为值的函数及匿名函数、柯里化、闭包及控制抽象以及计算器案例)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/856529

相关文章

Python函数作用域示例详解

《Python函数作用域示例详解》本文介绍了Python中的LEGB作用域规则,详细解析了变量查找的四个层级,通过具体代码示例,展示了各层级的变量访问规则和特性,对python函数作用域相关知识感兴趣... 目录一、LEGB 规则二、作用域实例2.1 局部作用域(Local)2.2 闭包作用域(Enclos

Python中re模块结合正则表达式的实际应用案例

《Python中re模块结合正则表达式的实际应用案例》Python中的re模块是用于处理正则表达式的强大工具,正则表达式是一种用来匹配字符串的模式,它可以在文本中搜索和匹配特定的字符串模式,这篇文章主... 目录前言re模块常用函数一、查看文本中是否包含 A 或 B 字符串二、替换多个关键词为统一格式三、提

MySQL count()聚合函数详解

《MySQLcount()聚合函数详解》MySQL中的COUNT()函数,它是SQL中最常用的聚合函数之一,用于计算表中符合特定条件的行数,本文给大家介绍MySQLcount()聚合函数,感兴趣的朋... 目录核心功能语法形式重要特性与行为如何选择使用哪种形式?总结深入剖析一下 mysql 中的 COUNT

MySQL 中 ROW_NUMBER() 函数最佳实践

《MySQL中ROW_NUMBER()函数最佳实践》MySQL中ROW_NUMBER()函数,作为窗口函数为每行分配唯一连续序号,区别于RANK()和DENSE_RANK(),特别适合分页、去重... 目录mysql 中 ROW_NUMBER() 函数详解一、基础语法二、核心特点三、典型应用场景1. 数据分

MySQL数据库的内嵌函数和联合查询实例代码

《MySQL数据库的内嵌函数和联合查询实例代码》联合查询是一种将多个查询结果组合在一起的方法,通常使用UNION、UNIONALL、INTERSECT和EXCEPT关键字,下面:本文主要介绍MyS... 目录一.数据库的内嵌函数1.1聚合函数COUNT([DISTINCT] expr)SUM([DISTIN

Python get()函数用法案例详解

《Pythonget()函数用法案例详解》在Python中,get()是字典(dict)类型的内置方法,用于安全地获取字典中指定键对应的值,它的核心作用是避免因访问不存在的键而引发KeyError错... 目录简介基本语法一、用法二、案例:安全访问未知键三、案例:配置参数默认值简介python是一种高级编

python 常见数学公式函数使用详解(最新推荐)

《python常见数学公式函数使用详解(最新推荐)》文章介绍了Python的数学计算工具,涵盖内置函数、math/cmath标准库及numpy/scipy/sympy第三方库,支持从基础算术到复杂数... 目录python 数学公式与函数大全1. 基本数学运算1.1 算术运算1.2 分数与小数2. 数学函数

MySQL中的索引结构和分类实战案例详解

《MySQL中的索引结构和分类实战案例详解》本文详解MySQL索引结构与分类,涵盖B树、B+树、哈希及全文索引,分析其原理与优劣势,并结合实战案例探讨创建、管理及优化技巧,助力提升查询性能,感兴趣的朋... 目录一、索引概述1.1 索引的定义与作用1.2 索引的基本原理二、索引结构详解2.1 B树索引2.2

从入门到精通MySQL 数据库索引(实战案例)

《从入门到精通MySQL数据库索引(实战案例)》索引是数据库的目录,提升查询速度,主要类型包括BTree、Hash、全文、空间索引,需根据场景选择,建议用于高频查询、关联字段、排序等,避免重复率高或... 目录一、索引是什么?能干嘛?核心作用:二、索引的 4 种主要类型(附通俗例子)1. BTree 索引(

Spring如何使用注解@DependsOn控制Bean加载顺序

《Spring如何使用注解@DependsOn控制Bean加载顺序》:本文主要介绍Spring如何使用注解@DependsOn控制Bean加载顺序,具有很好的参考价值,希望对大家有所帮助,如有错误... 目录1.javascript 前言2. 代码实现总结1. 前言默认情况下,Spring加载Bean的顺