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)(_ / _))
}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/496399.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【华大 HC32L110】调用`printf`和串口接收中断的冲突问题解决

华大单片机 HC32L110调用printf和串口接收中断的冲突问题解决,经过查找是官方库 去使能了 串口的接收功能,记录解决问题的过程 目录 1.硬件MCU资料2. printf和串口接收中断的冲突解决3.重新封装 fputc 函数4.查找问题,发现是官方库配置有误5. 查找寄存器手册,修改寄存器配置…

智慧光伏:企业无纸化办公

随着科技的快速发展,光伏技术不仅成为推动绿色能源革命的重要力量,更在企业办公环境中扮演起引领无纸化办公的重要角色。智慧光伏不仅为企业提供了清洁、可持续的能源,更通过智能化的管理方式,推动企业向无纸化办公转型&#xff0…

MySQL三种开窗函数详细用法,图文详解

开窗函数的详细用法 第一章、开窗函数的语法1.1)从聚合开窗函数讲起1.2)开窗函数之取值1.3)排名开窗函数 第一章、开窗函数的语法 开窗函数的语法为:over(partition by 列名1 order by 列名2 ),括号中的两个关键词par…

谈到视频编码标准时,实际指什么?

当在谈论一个视频编码标准时,实际指是什么?相关论文,还是编解码器代码,或者其他东西? 比如H.264视频编码标准,当论文或书上看到它时,通常是H.264/AVC的形式,如下: It was…

Linux:详解TCP协议(一)

文章目录 认识TCPTCP协议段格式 本篇主要总结的是TCP协议的一些字段 认识TCP TCP协议全称是传输控制协议,也就是说是要对于数据的传输进行一个控制 以上所示的是对于TCP协议进行数据传输的一个理解过程 全双工 至此就可以对于TCP协议是全双工的来进行理解了&…

蓝桥OJ3510 冶炼金属(暴力+二分)

冶炼金属 学习了b站Turing_Sheep的思路 一、暴力模拟 思路: b[i] a[i] / v b[1] a[1] / v b[2] a[2] / v .... b[n] a[n] / v 以上列举中v要满足所有的记录,但凡一个记录不满足,v就不满足题意。 从小到大列举v,设置v最大为1e6 设置一个标…

鸿蒙开发之ArkUI组件常用组件-CustomDialog/Video

CustomDialog 自定义弹窗(CustomDialog)可用于广告、中奖、警告、软件更新等与用户交互响应操作。我们可以通过CustomDialogController类显示自定义弹窗。 创建自定义弹窗 使用CustomDialog装饰器装饰自定义弹窗CustomDialog装饰器用于装饰自定义弹窗&a…

Vuepress 2从0-1保姆级进阶教程——美化与模板

Vuepress 2 专栏目录 1. 入门阶段 Vuepress 2从0-1保姆级入门教程——环境配置篇Vuepress 2从0-1保姆级入门教程——安装流程篇Vuepress 2从0-1保姆级入门教程——文档配置篇Vuepress 2从0-1保姆级入门教程——范例与部署 2.进阶阶段 Vuepress 2从0-1保姆级进阶教程——全文搜索…

【Java程序设计】【C00388】基于(JavaWeb)Springboot的校园竞赛管理系统(有论文)

Springboot的校园竞赛管理系统(有论文) 项目简介项目获取开发环境项目技术运行截图 博主介绍:java高级开发,从事互联网行业六年,已经做了六年的毕业设计程序开发,开发过上千套毕业设计程序,博客…

基于ZHW3548的红外额温枪解决方案

红外额温枪,非接触式测量最典型的方法是红外测温。自红外辐射原理被发现以来,红外技术被广泛应用在温度测量中。红外测温仪具有测温范围广,响应速度快,灵敏度高等特点。红外耳温枪、红外额温计和红外筛检仪都属于非接触式体温计。…

实验3 中文分词

必做题: 数据准备:academy_titles.txt为“考硕考博”板块的帖子标题,job_titles.txt为“招聘信息”板块的帖子标题,使用jieba工具对academy_titles.txt进行分词,接着去除停用词,然后统计词频,最…

鱼眼相机的测距流程及误差分析[像素坐标系到空间一点以及测距和误差分析]

由于最近在整理单目测距的内容,顺手也总结下鱼眼相机的测距流程和误差分析,如果有错误,还请不吝赐教。 参考链接: 鱼眼镜头的成像原理到畸变矫正(完整版) 相机模型总结(针孔、鱼眼、全景) 三维…

Linux 基础IO [缓冲区文件系统]

💓博主CSDN主页:麻辣韭菜-CSDN博客💓   ⏩专栏分类:http://t.csdnimg.cn/G90eI⏪   🚚代码仓库:Linux: Linux日常代码练习🚚   🌹关注我🫵带你学习更多Linux知识   🔝 目录 前言…

HarmonyOS实战开发-实现自定义弹窗

介绍 本篇Codelab基于ArkTS的声明式开发范式实现了三种不同的弹窗,第一种直接使用公共组件,后两种使用CustomDialogController实现自定义弹窗,效果如图所示 相关概念 AlertDialog:警告弹窗,可设置文本内容和响应回调…

Swift 从获取所有 NSObject 对象聊起:ObjC、汇编语言以及底层方法调用链(三)

概览 承接上一篇博文: Swift 从获取所有 NSObject 对象聊起:ObjC、汇编语言以及底层方法调用链(二)我们在其中讨论了如何使用第三方强大通用的钩子库 SwiftHook 来协助我们完成 NSObject 构造器 init 的 SWIZZ 操作。我们还讨论了为什么用 print 打印对象信息时会发生崩溃…

在Windows系统上安装多个 Nodejs

前言 在Windows系统安装Nodejs 在Windows系统上安装多个 Nodejs v14.16.1安装位置 D:\sde\nodejs\node-v14.16.1-win-x64 v16.20.2安装位置 D:\sde\nodejs\node-v16.20.2-win-x64 v18.20.0安装位置 D:\sde\nodejs\node-v18.20.0-win-x64 v20.12.0安装位置 D:\sde\nod…

YOLOv9改进策略 :neck优化 | 路径融合GFPN,小目标到大目标一网打尽 | 轻骨干重Neck的轻量级目标检测器GiraffeDet

💡💡💡本文改进内容:设计了一种新的路径融合GFPN:包含跳层与跨尺度连接,改进思路来自ICLR2022 GiraffeDet的核心思想。 💡💡💡GFPN和六个检测头结合,这种跳层…

集体出走的Stability AI 发布全新代码大模型,3B以下性能最优,超越Code Llama和DeepSeek-Coder

Stability AI又有新动作!程序员又有危机了? 3月26日,Stability AI推出了先进的代码语言模型Stable Code Instruct 3B,该模型是在Stable Code 3B的基础上进行指令调优的Code LM。 Stability AI 表示,Stable Code Instru…

【python】flask执行上下文context,请求上下文和应用上下文原理解析

✨✨ 欢迎大家来到景天科技苑✨✨ 🎈🎈 养成好习惯,先赞后看哦~🎈🎈 🏆 作者简介:景天科技苑 🏆《头衔》:大厂架构师,华为云开发者社区专家博主,…

2024河北石家庄矿业矿山展览会|河北智慧矿山展会|河北矿博会

2024中国(石家庄)国际矿业博览会      时间:2024年7月4-6日 地点:石家庄国际会展中心.正定      随着全球经济的持续增长和矿产资源需求的不断攀升,矿业行业正迎来前所未有的发展机遇。作为矿业领域的盛会&…