【Scala---04】函数式编程 『 函数 vs 方法 | 函数至简原则 | 函数式编程』
文章目录
- 1. 函数 vs 方法
- 1.1 方法
- (1) 定义方法
- (2) 运算符即方法
- 1.2 函数
- (1) 定义函数
- (2) 匿名函数
- 1.3 方法转为函数
- 1.4 可变参数&默认参数
- 2. 函数至简原则
- 3. 函数式编程
- 3.1 函数式编程思想
- 3.3 函数柯里化&闭包
- 3.5 递归 & 尾递归
- 4. 补充
- 4.1 访问元祖元素
- 4.2 =>的含义
- 4.3 下划线的使用总结
1. 函数 vs 方法
在Java中方法与函数没区别,但是在Scala中方法和函数是不一样的。Java是面向对象的,Scala是面向函数式编程的,主要体现在如下4点:
Java | 对象可以作为一个值传递 | 对象可以作为参数传递 | 对象可以作为返回值传递 | 可以调用对象 |
---|---|---|---|---|
Scala | 函数可以作为一个值传递 | 函数可以作为参数传递 | 函数可以作为返回值传递 | 可以调用函数 |
Scala | 方法不可以作为一个值传递 | 方法不可以作为参数传递 | 方法不可以作为返回值传递 | 可以调用函数 |
可以看出Scala中函数比方法更加强大,而函数相比于方法最重要的功能就是函数能作为参数传递,也就是说a和b进行的操作不是写死的,而是可变的。
- 从位置上理解:方法 只能在类中定义,做为类的属性;函数 可以在任何地方定义。
- 从是否可以重载的角度:方法定义在类中可以实现重载;函数不可以重载。
- 从运行位置角度:方法是保存在方法区;函数是保存在堆中。
1.1 方法
(1) 定义方法
定义方法语法如下:
object 类名 {def 方法名([变量:变量类型,变量:变量类型]):返回值类型 = {方法体}
}
比如:
-
方法不能作为值传递
object Main {def main(args: Array[String]): Unit = {def add(x:Int, y:Int):Int = {x + y}val result = add // 会报错println(result)} }
-
方法不能作为参数传递
object Main {def main(args: Array[String]): Unit = {// 1. 定义calculate方法def calculate(x: Int, y: Int, func: (Int, Int) => Int): Int = { // x与y进行func操作,这个func函数需要指名 形参类型和返回值func(x, y)}// 2. 定义add方法def add(x:Int, y:Int):Int = {x + y}// 3. 函数作为参数传递val result = calculate(2, 3, add) // 不会报错,自动转为函数传递println(result)} }
-
方法不能作为返回值传递
object Main {def main(args: Array[String]): Unit = {// 1. 定义getFunc方法def getFunc() = { // x与y进行func操作,这个func函数需要指名 形参类型和返回值def func(x: Int, y: Int) = {x + y} func // 会报错}// 2. 得到函数println(getFunc())} }
-
方法可以直接调用
object Main {def main(args: Array[String]): Unit = {def add(x: Int, y: Int) = x + yprintln(add(2, 3)) // 输出:5} }
(2) 运算符即方法
- 所有的运算符本质上是方法。比如查看
Int
类
可以看到类中定义了很多以运算符命名的方法
因此,以下两种方法是等价的val a = 1 + 2val a = 1.+(2)
- 反过来,可以定义这样的方法,并调用
-
例子1
object Cal {def say(x:Int):Int = x }object Main {def main(args: Array[String]): Unit = {// 1. 用 类.方法名(参数列表) 形式调用方法var result1 = Cal.say(3)// 2. 用 类 方法 参数列表 形式调用方法var result2 = Cal say (3) var result3 = Cal say 3 // 如果参数列表只有一个值,括号是可以省略的} }
-
例子2
object Main {def say(x:Int):Int = xdef main(args: Array[String]): Unit = {// 1. 用 类.方法名(参数列表) 形式调用方法var result1 = this.say(3)// 2. 用 类 方法 参数列表 形式调用方法var result2 = this say (3) // 如果参数列表只有一个值,括号是可以省略的var result3 = this say 3} }
-
1.2 函数
(1) 定义函数
Scala中有23个函数接口类,函数的本质就是实现这些接口类来实现强大的功能:
Function0
:无参数,无返回值Function1
:…
定义函数语法如下:
object 类名 {def 函数名:([变量类型,变量类型])=>返回值类型 = ([变量:变量类型,变量:变量类型]) => {方法体}
}
比如:
-
函数可以作为一个值传递
object Main {def main(args: Array[String]): Unit = {val add = (x:Int, y:Int) => x + yval result = add // 不会报错println(result) } }
-
函数可以作为参数传递,此时需要指名函数的类型。格式为:
(参数类型)=>返回值类型
object Main {def main(args: Array[String]): Unit = {// 1. 定义calculate方法def calculate(x:Int, y:Int, func:(Int, Int)=>Int): Int = { // x与y进行func操作,这个func函数需要指名 形参类型和返回值func(x, y)}// 2. 定义add函数def add = (x:Int, y:Int) => x + y// 3. 函数作为参数传递val result = calculate(2, 3, add)// 4. 输出println(result) // 输出5} }
-
函数可以作为返回值传递
object Main {def main(args: Array[String]): Unit = {// 1. 定义getFunc方法def getFunc() = { // x与y进行func操作,这个func函数需要指名 形参类型和返回值val func = (x:Int, y:Int) => x + yfunc}// 2. 得到函数println(getFunc())// 3. 得到函数并执行函数println(getFunc()(2, 3)) // 输出5} }
-
函数可以执行
object Main {def main(args: Array[String]): Unit = {val add = (x:Int, y:Int) => x + yprintln(add(2, 3))} }
(2) 匿名函数
匿名函数与函数的语法区别就在于前者是val
关键字,后者是def
关键字。比如:
匿名函数简化了函数值传递:
注意:这只会定义一个函数,也不会执行函数。这点和Java不一样,java的lambda表达式是会创建对象,并执行构造方法。
1.3 方法转为函数
-
通用转换方式,在方法名后面 + 空格 + _ 即可,语法为:
方法名 _
object Main {def main(args: Array[String]): Unit = {def add(x:Int, y:Int):Int = {x + y}val result = add _ // 将方法转为函数println(result(2, 3)) // 输出:5} }
-
在参数处将方法转为函数时,可以简化,去掉
_
,直接方法名
object Main {def main(args: Array[String]): Unit = {// 1. 定义calculate方法def calculate(x: Int, y: Int, func: (Int, Int) => Int): Int = { // x与y进行func操作,这个func函数需要指名 形参类型和返回值func(x, y)}// 2. 定义add函数def add(x:Int, y:Int):Int = {x + y}// 3. 函数作为参数传递val result1 = calculate(2, 3, add _) // 此时可优化,去掉 空格_val result2 = calculate(2, 3, add) // 优化后的代码} }
1.4 可变参数&默认参数
object Test03_FunArgs {def main(args: Array[String]): Unit = {// (1)可变参数:在类型后面加*号def sayHi(names:String*):Unit = {println(s"hi $names")}sayHi()sayHi("linhai")sayHi("linhai","jinlian")// (2)可变参数必须在参数列表的最后def sayHi1(sex: String,names:String*):Unit = {println(s"hi $names")}// (3)参数默认值def sayHi2(name:String = "linhai"):Unit = {println(s"hi ${name}")}sayHi2("linhai")sayHi2()// (4)默认值参数在使用的时候 可以不在最后def sayHi3( name:String = "linhai" , age:Int):Unit = {println(s"hi ${name}")}// (5)带名参数:指调用方法时,指定传参顺序sayHi3(age = 10, name = "niu")}
}
2. 函数至简原则
注意:方法最后一行的return可以省略,但是除此之外都不能省略。比如
object Test04_FuncSimply {def main(args: Array[String]): Unit = {//(1)return可以省略,Scala会使用方法体的最后一行代码作为返回值def func1(x: Int, y: Int): Int = {x + y}// (2)如果方法体只有一行代码,可以省略花括号def func2(x: Int, y: Int): Int = x + y//(3)返回值类型如果能够推断出来,那么可以省略(:和返回值类型一起省略)// 此时,函数就变为了数学表达式的形式:f(x, y) = x + ydef func3(x: Int, y: Int) = x + y//(4)如果有return,则不能省略返回值类型,必须指定def func4(x: Int, y: Int): Int = {if (x < 20) {return x + y}2 * x + 3 * y}//(5)如果方法明确声明unit,那么即使函数体中使用return关键字也不起作用def func5(x: Int, y: Int): Unit = return x + y//(6)Scala如果期望是无返回值类型,可以省略等号def func6(x: Int, y: Int) {println(x + y)}// (7)如果方法无参,但是声明了参数列表,那么调用时,小括号,可加可不加def func7(): Unit = {println("hello")}// (8)如果方法没有参数列表,那么小括号可以省略,调用时小括号必须省略def func8 {println("hello")}// (9)如果不关心函数名,只关心映射逻辑,就会变为lambda表达式(x:Int, y:Int) => {println(x + y)}val func = (x:Int, y:Int) => {println(x + y)} // 如果要设置函数名可以这样。此时,func就是函数名}
}
3. 函数式编程
3.1 函数式编程思想
- 函数式编程思想:① 当做数学题,y = f(x),重要的是映射关系。② 使用val,在分布式上计算后不会产生歧义
- 通过前面可以知道,定义函数有3种形式:
- 方法转函数。先定义方法,再
方法名 _
- 直接定义函数
def
- 匿名函数
- 方法转函数。先定义方法,再
一看到
=>
或 一看到_
,就要想到这是表示函数。
3.3 函数柯里化&闭包
-
闭包:内层函数用到了外层函数变量,如果直接调用内层函数会取不到外层函数的这个变量值。此时,内层函数(万物皆对象,函数也是对象)的堆中的对象会保留一份引用到外层函数的值。
闭包参考链接 -
函数柯里化:将一个接收多个参数的函数转化成一个一个接受参数的函数过程,可以简单的理解为一种特殊的参数列表声明方式。函数柯里化
object TestFunction {val sum = (x: Int, y: Int, z: Int) => x + y + z// 函数柯里化的底层逻辑:本质是将函数作为返回值val sum1 = (x: Int) => {y: Int => { // 匿名函数z: Int => { // 匿名函数x + y + z}}}// 函数柯里化的另一种简单表达val sum2 = (x: Int) => (y: Int) => (z: Int) => x + y + z// 方法也有函数柯里化def sum3(x: Int)(y: Int)(z: Int) = x + y + zdef main(args: Array[String]): Unit = {sum(1, 2, 3)sum1(1)(2)(3) // sum1(1)调用完后,返回一个函数; sum1(1)(2)是调用返回的函数; .......sum2(1)(2)(3)sum3(1)(2)(3)} }
3.5 递归 & 尾递归
-
递归与Java中的递归一样:前面知道scala的方法返回值是可以省略的,默认分配返回值类型,但是 如果方法是递归方法,则必须指定方法的返回值类型,否则会报错。
object Test{def main(args: Array[String]): Unit = {// 实现阶乘def fact(n : Int) : Int = { // 必须指名方法的返回值类型// 跳出递归if(n == 1) return 1// 递归逻辑n * fact(n - 1)}// 调用阶乘方法println(fact(5))} }
-
尾递归:递归是将每次调用函数/方法会压入到栈中,是累计使用资源,容易造成栈溢出;而尾递归是覆盖使用资源,不会造成栈溢出。所以,尾递归资源利用率更加高。尾递归参考链接
一般支持函数式编程语言都支持尾递归;但是Java不支持尾递归。
4. 补充
4.1 访问元祖元素
变量名._数字
比如:x._1 表示访问x的第一个元素
4.2 =>的含义
https://blog.csdn.net/qq_43546676/article/details/130992479
4.3 下划线的使用总结
https://blog.csdn.net/qq_43546676/article/details/130874779
相关文章:
【Scala---04】函数式编程 『 函数 vs 方法 | 函数至简原则 | 函数式编程』
文章目录 1. 函数 vs 方法1.1 方法(1) 定义方法(2) 运算符即方法 1.2 函数(1) 定义函数(2) 匿名函数 1.3 方法转为函数1.4 可变参数&默认参数 2. 函数至简原则3. 函数式编程3.1 函数式编程思想3.3 函数柯里化&闭包3.5 递归 & 尾递归 4. 补充4.1 访问元祖元素4.2 &g…...
[华为OD] B卷 树状结构查询 200
题目: 通常使用多行的节点、父节点表示一棵树,比如 西安 陕西 陕西 中国 江西 中国 中国 亚洲 泰国 亚洲 输入一个节点之后,请打印出来树中他的所有下层节点 输入描述 第一行输入行数,下面是多行数据,每行以空…...
基于机器学习的学生学习行为自主评价设计与实现
管理员功能: a)学生学习数据管理:可查看学生学习的详情,编辑学生学习的内容,删除和添加学生学习,设置学生学习库存。 b)角色管理:增加删除学生用户,分配学生用户权限,查看学生用户…...
toml与json联系对比
前言 本文简单介绍toml;并且和json转化做对比,以及我对toml设计的理解。 参考: TOML: 简体中文 v1.0.0 json和toml转化工具 在线JSON转toml-toml转JSON - bejson在线工具 正文 数组 说白了,就是一个变量名,有多个…...
(已解决)org.springframework.amqp.rabbit.support.ListenerExecutionFailedException
报错截图 解决方案 1、登录rabbitMQ网址,删除所有队列 2、重启rabbitMQ 亲测有效!!!亲测有效!!!亲测有效!!!...
基于FPGA的数字信号处理(9)--定点数据的两种溢出处理模式:饱和(Saturate)和绕回(Wrap)
1、前言 在逻辑设计中,为了保证运算结果的正确性,常常需要对结果的位宽进行扩展。比如2个3bits的无符号数相加,只有将结果设定为4bits,才能保证结果一定是正确的。不然,某些情况如77 14(1110),如果结果只…...
基于STM32的宠物箱温度湿度监控系统毕业设计
基于STM32的宠物箱温度湿度监控系统毕业设计 一、项目背景与意义 随着人们生活水平的提高,养宠物已经成为一种流行趋势。然而,对于宠物的居住环境,尤其是温度与湿度的控制,是确保宠物健康的关键。本项目旨在设计一款基于STM32微…...
Linux sudo 指令
sudo命令 概念: sudo是linux下常用的允许普通用户使用超级用户权限的工具,允许系统管理员让普通用户执行一些或者全部的root命令,如halt,reboot,su等。这样不仅减少了root用户的登录和管理时间,同样也提高…...
【NumPy数组】:深入了解numpy.linspace()函数
一、numpy.linspace()函数的原理 numpy.linspace()函数的核心原理是在指定的起始值和终止值之间,按照给定的元素个数,生成等间隔的数值序列。与numpy.arange()函数不同,numpy.linspace()生成的是等间隔的数值,而不是等差的数值&a…...
计算机网络实验二:交换机的基本配置与操作
实验二:交换机的基本配置与操作 一、实验要求 (1)掌握windows网络参数的设置(TCP/IP协议的设置); (2)掌握交换机命令行各种操作模式的区别,以及模式之间的切换; (3)掌握交换机的全局的基本配置; (4)掌握交换机端口的常用配置参数; (5)查看交换机系统和…...
宏的优缺点?C++有哪些技术替代宏?(const)权限的平移、缩小
宏的优缺点? 优点: 1.增强代码的复用性。【减少冗余代码】 2.提高性能,提升代码运行效率。 缺点: 1.不方便调试宏。(因为预编译阶段进行了替换) 2.导致代码可读性差,可维护性差࿰…...
2024数维杯数学建模选题建议及各题思路来啦!
大家好呀,2024数维杯数学建模挑战赛开始了,来说一下初步的选题建议吧: 首先定下主基调, 本次数维杯建议选B。难度上C>A>B。B题目是比较经典的数据分析类题目,主要做统计分析差异显著性以及相关…...
centos的常用命令
CentOS是一个基于Red Hat Enterprise Linux(RHEL)的开源操作系统,常用于服务器环境。以下是一些CentOS中常用的命令: 文件和目录管理: ls:列出目录中的文件。 ls -l:以长格式列出文件和目录的…...
【Android】使用Handler实现一个定时器
需求 实现一个定时任务,每隔一秒执行一次 实现 使用Handler实现 private Handler topUIHandler;private void initTopUiHandler() {topUIHandler new Handler(getMainLooper()) {Overridepublic void handleMessage(Message msg) {//执行这个定时任务updateTop…...
Java | Leetcode Java题解之第80题删除有序数组中的重复项II
题目: 题解: class Solution {public int removeDuplicates(int[] nums) {int n nums.length;if (n < 2) {return n;}int slow 2, fast 2;while (fast < n) {if (nums[slow - 2] ! nums[fast]) {nums[slow] nums[fast];slow;}fast;}return sl…...
java后端15问!
前言 最近一位粉丝去面试一个中厂,Java后端。他说,好几道题答不上来,于是我帮忙整理了一波答案 G1收集器JVM内存划分对象进入老年代标志你在项目中用到的是哪种收集器,怎么调优的new对象的内存分布局部变量的内存分布Synchroniz…...
OmniPlan Pro 4 for Mac中文激活版:项目管理的新选择
OmniPlan Pro 4 for Mac作为一款专为Mac用户设计的项目管理软件,为用户提供了全新的项目管理体验。其直观易用的界面和强大的功能特性,使用户能够轻松上手并快速掌握项目管理要点。 首先,OmniPlan Pro 4 for Mac支持自定义视图,用…...
二叉树的广度优先遍历 - 华为OD统一考试(D卷)
OD统一考试(D卷) 分值: 200分 题解: Java / Python / C++ 题目描述 有一棵二叉树,每个节点由一个大写字母标识(最多26个节点)。 现有两组字母,分别表示后序遍历(左孩子->右孩子->父节点)和中序遍历(左孩子->父节点->右孩子)的结果,请输出层次遍历的结…...
代码随想录-算法训练营day31【贪心算法01:理论基础、分发饼干、摆动序列、最大子序和】
代码随想录-035期-算法训练营【博客笔记汇总表】-CSDN博客 第八章 贪心算法 part01● 理论基础 ● 455.分发饼干 ● 376. 摆动序列 ● 53. 最大子序和 贪心算法其实就是没有什么规律可言,所以大家了解贪心算法 就了解它没有规律的本质就够了。 不用花心思去研究其…...
如何使用Transformer-TTS语音合成模型
1、技术原理及架构图 Transformer-TTS主要通过将Transformer模型与Tacotron2系统结合来实现文本到语音的转换。在这种结构中,原始的Transformer模型在输入阶段和输出阶段进行了适当的修改,以更好地处理语音数据。具体来说,Transformer-TT…...
【Python】JSON数据的使用
一、JSON JSON是什么: JSON(JavaScript Object Notation)是一种轻量级的数据交换格式,它以易于理解和生成的文本格式来描述数据对象。JSON最初是由Douglas Crockford在2001年提出的,它的设计受到了JavaScript对象字面量…...
C语言头文件的引入使用<>和““有什么区别
在C语言中,引入头文件时使用<>和""有以下主要区别: 搜索路径不同: 当使用#include <filename.h>时,编译器会首先在系统目录中搜索头文件。这些系统目录通常包含了标准库的头文件,如stdio.h、std…...
Qt 类的设计思路详解
Qt 是一个跨平台的 C++ 应用程序开发框架,它提供了丰富的类库和工具,用于开发图形用户界面、网络应用、数据库集成和文件 I/O 等功能。Qt 的设计思路涉及到诸多方面,包括跨平台性、模块化、可扩展性、性能等。本文将从这些方面详细说明 Qt 类的设计思路。 1. 跨平台性 Qt 最…...
五一超级课堂---Llama3-Tutorial(Llama 3 超级课堂)---第一节 Llama 3 本地 Web Demo 部署
课程文档: https://github.com/SmartFlowAI/Llama3-Tutorial 课程视频: https://space.bilibili.com/3546636263360696/channel/collectiondetail?sid2892740&spm_id_from333.788.0.0 操作平台: https://studio.intern-ai.org.cn/consol…...
Redis20种使用场景
Redis20种使用场景 1缓存2抽奖3Set实现点赞/收藏功能4排行榜5PV统计(incr自增计数)6UV统计(HeyperLogLog)7去重(BloomFiler)8用户签到(BitMap)9GEO搜附近10简单限流11全局ID12简单分…...
vue3获取原始值
在 Vue 3 中,_rawValue 是 ref 内部的一个属性,它用来存储 ref 的原始值,也就是未经响应式处理的值。这个属性主要用于 Vue 的内部逻辑,以帮助区分 ref 的当前值 (value) 和原始输入值 (_rawValue)。对于大多数开发者来说…...
“感恩遇到你,郭护士!”佛山市一医院 护士回家途中救了位老奶奶
“感恩遇见你,我感谢郭护士关爱长者、热心助人的高尚行为……”看着信件上感谢的话语,郭琳玲的内心感动不已。而这一封亲笔手写的感谢信,是来自一位将近八十岁的老奶奶。 郭琳玲是佛山市第一人民医院创伤重症功能神经外科的一名护士。4月30日…...
Java面试常见问题
操作系统 1.Q: 在操作系统中,什么时候会发生用户态到内核态的切换 A: 操作系统中,用户态和内核态是两种不同的权限级别,他们对应着不同的执行环境和执行权限。用户态事指程序在一般的运行情况下的的级别,它具有别较低的权限级别&…...
概率论 科普
符号优先级 概率公式中一共有三种符号:分号 ; 、逗号 , 、竖线 | 。 ; 分号代表前后是两类东西,以概率P(x;θ)为例,分号前面是x样本,分号后边是模型参数。分号前的 表示的是这个式子用来预测分布的随机变量x,分号后的…...
全面解读快递查询API接口,帮你轻松查询快递物流信息
随着电子商务的快速发展,快递业务正变得越来越重要。无论是买家还是卖家,都希望能够及时了解自己的快递物流信息,以便更好地掌控商品的运输过程。而现在,通过快递查询API接口,我们可以实现快速、准确地查询几百家国内快…...
h5响应式网站/长沙营销型网站建设
在5G的大势所趋之下,手机厂商也逐渐展露了各自在5G上的布局,其中华为与OPPO两大头部厂商也都推出了自家的5G手机:华为Mate30 Pro 5G和OPPO Reno3 Pro。这两部双模5G手机可以说都是“黑科技”于一身,旨在为消费者带去更好的体验&am…...
网站怎样做才能排名靠前/营销技巧
1. 涉及平台 平台管理、商家端(PC端、手机端)、买家平台(H5/公众号、小程序、APP端(IOS/Android)、微服务平台(业务服务) 2. 核心架构 Spring Cloud、Spring Boot、Mybatis、Redis 3. 前端框架…...
大连市网站制作电话/新东方线下培训机构官网
在使用php开发之中大家都习惯使用gb类库来处理图像信息,但是函数很多的gb类库也是很头疼,使用起来要一个个的查询函数和看官方手册,下面将介绍一个很强大的图像处理工具----ImageMagick,这个在liunx下面处理图像信息将会更简洁。先…...
苏州服务器托管哪家好/站长工具的使用seo综合查询排名
01 下载 macOS 系统安装程序的方法 本文来自: https://discussionschinese.apple.com/docs/DOC-250004259 简介 Mac 用户时不时会需要下载 macOS 的安装程序,目的不同,或者升级或者降级,或者研究或者收藏。为了方便不同用户,除…...
广州营销型网站建设公司哪家名气大/制作网站
需求说明: /* *需求说明: *获取元素:tBodies,tHead,tFoot,rows,cells *表格的创建 *数据添加 *隔行变色 *删除操作,剩余表格重新计算,实现隔行变色*/HTML: <table id"table1"><tbody><tr><th>编…...
开发商交房必备条件/深圳优化seo
插在电脑上实验时若出现 ATCREG? CREG: 0,2 可能是usb口供电不足所致,换至主机箱后面usb口后问题解决,返回值CREG: 0,1转载于:https://www.cnblogs.com/prayer521/p/6690257.html...