Scala函数式编程
创始人
2025-05-31 15:10:03

一、基本函数编程

在Scala 中函数式编程和面向对象编程完美融合在一起了

1 基础概念

1)    面向对象编程
解决问题,分解对象,行为,属性,然后通过对象的关系以及行为的调用来解决问题。

对象:用户
行为:登录、连接 JDBC、读取数据库属性:用户名、密码
Scala 语言是一个完全面向对象编程语言。万物皆对象对象的本质:对数据和行为的一个封装


2)    函数式编程
解决问题时,将问题分解成一个一个的步骤,将每个步骤进行封装(函数),通过调用这些封装好的步骤,解决问题。
例如:请求->用户名、密码->连接 JDBC->读取数据库
Scala 语言是一个完全函数式编程语言。万物皆函数。函数的本质:函数可以当做一个值进行传递
 

				// (1)函数定义def f(arg: String): Unit = {println(arg)}// (2)函数调用// 函数名(参数)f("hello world")

 2 函数和方法的区别

1)核心概念

  • 为完成某一功能的程序语句的集合,称为函数。
  • 类中的函数称之方法

2)案例实操

  • Scala 语言可以在任何的语法结构中声明任何的语法
  • 函数没有重载和重写的概念;方法可以进行重载和重写
  • Scala 中函数可以嵌套定义

object TestFunction {// 方法可以进行重载或重写,也可以执行def main():Unit={}def main(args: Array[String]): Unit = {// (1)Scala 语言可以在任何的语法结构中声明任何的语法import java.util.Datenew Date()// (2) 函数没有重写和重载的概念,重写报错def test():Unit = {println("test")}//def test(i:Unit):Unit = {  // error//	println("test")//}// (3)Scala 中函数可以嵌套定义def myFun():Unit={println()}}

3 函数定义

3.1 无参,无返回值

def test1(): Unit ={println("无参,无返回值")
}
test1()

 3.2 无参,有返回值

def test2():String={return "无参,有返回值"
}
println(test2())

 3.3 有参,无返回值

def test3(s:String):Unit={ println(s)
}
test3("haha")

3.4 有参,有返回值

def test4(s:String):String={ return s+"有参,有返回值"
}
println(test4("hello "))

3.5 多参,无返回值

def test5(name:String, age:Int):Unit={ println(s"$name, $age")
}

4 函数参数

(1)可变参数
(2)如果参数列表中存在多个参数,那么可变参数一般放置在最后
(3)参数默认值,一般将有默认值的参数放置在参数列表的后面
(4)带名参数

4.1 可变参数

		def test(s: String*): Unit = {println(s)}test()test("haha", "lala")

 4.2 如果参数列表中存在多个参数,那么可变参数一般放置在最后

		def test(s0: String, s: String*): Unit = {println(s"${s0}有学生:${s}")}test("sfm", "zmy", "hlq", "zdc", "...")

 

 4.3 参数默认值,一般将有默认值的参数放置在参数列表的后面

		def test(name: String, age: Int = 23): Unit = {println(s"${name}今年${age}岁")}test("chen chen")// 如果参数传递了值,那么会覆盖默认值test("chen chen", 18)

 

 

4.4  带名参数

test(name="辰辰")

5 函数至简原则

函数至简原则:能省则省

  • return 可以省略,Scala 会使用函数体的最后一行代码作为返回值
  • 如果函数体只有一行代码,可以省略花括号
  • 返回值类型如果能够推断出来,那么可以省略(:和返回值类型一起省略)
  • 如果有 return,则不能省略返回值类型,必须指定
  • 如果函数明确声明unit,那么即使函数体中使用 return 关键字也不起作用
  • Scala 如果期望是无返回值类型,可以省略等号
  • 如果函数无参,但是声明了参数列表,那么调用时,小括号,可加可不加
  • 如果函数没有参数列表,那么小括号可以省略,调用时小括号必须省略
  • 如果不关心名称,只关心逻辑处理,那么函数名(def)可以省略

5.0 函数标准写法

		// (0)函数标准写法def f(s: String): String = {return s + " chen chen"}println(f("Hello"))

5.1 return 可以省略,Scala 会使用函数体的最后一行代码作为返回值

		def f1(s: String): String = {s + " chen chen1"}println(f1("Hello"))

5.2 如果函数体只有一行代码,可以省略花括号

		def f2(s: String): String = s + " chen chen1"println(f2("Hello"))

 5.3 返回值类型如果能够推断出来,那么可以省略(:和返回值类型一起省略)

		def f3(s: String) = s + " chen chen1"println(f3("Hello"))

5.4 如果有 return,则不能省略返回值类型,必须指定

		def f4(s: String): String = {return s + " chen chen"}println(f4("Hello"))

5.5 如果函数明确声明unit,那么即使函数体中使用 return 关键字也不起作用

		def f5(s: String): Unit = {return s + " chen chen"}println(f5("Hello"))

 5.6 Scala 如果期望是无返回值类型,可以省略等号(将无返回值的函数称之为过程)

		def f6(s: String) {println(s + " chen chen")}f6("Hello")

5.7  如果函数无参,但是声明了参数列表,那么调用时,小括号,可加可不加

		def f7() = "明宇"println(f7)println(f7())

 

 5.8 如果函数没有参数列表,那么小括号可以省略,调用时小括号必须省略

		def f8 = "辰辰"println(f8)//println(f8()) // error

5.9  如果不关心名称,只关心逻辑处理,那么函数名、def 可以省略【匿名函数】

		() => {s"nihao"}//	调用def f9 = (x: String) => {s"nihao,${x}"}println(f9("ming yu"))

二、高阶函数编程

所谓的高阶函数,其实就是将函数当成一个类型来使用,而不是当成特定的语法结构。

 1 函数可以作为值进行传递

package com.mingyu.spark.core.testobject Test_High_Fun {def main(args: Array[String]): Unit = {def f(name: String) = {println(s"hello,${name}")}// 将函数f作为对象赋值给v1// Function1 -> 有一个参数的函数类型// [String,Unit] -> 参数类型为String,返回值类型为Unit// 函数对象参数最多有22个,并不是函数的参数最多有22个val v1: Function1[String, Unit] = f _//println(v1.getClass.getSimpleName) // Test_High_Fun$$$Lambda$1/517938326v1 //不会执行,只是一个对象v1("mingyu")// 以上方法太麻烦,使用以下方法def test2(name: String, age: Int): Unit = {println(s"${name}今年${age}岁了:)")}// v2的类型就是 (String,Int) => Unit// 前面是参数类型,后面是返回值类型val v2 = test2 _v2("cc", 23)}
}

 

 2 函数可以作为参数进行传递

package com.mingyu.spark.core.testobject Test_High_Fun {def main(args: Array[String]): Unit = {//	函数对象作为参数使用def fun(): Unit = {println("test...")}// 参数类型是函数对象def test(f: () => Unit): Unit = {f()}val f = fun _test(f) // test...}
}

3 函数可以作为函数返回值返回

package com.mingyu.spark.core.testobject Test_High_Fun {def main(args: Array[String]): Unit = {def outer(): () => Unit = {def inner(): Unit = {println("inner...")}inner _}outer()() // inner...}
}

4 匿名函数

object Test {def main(args: Array[String]): Unit = {def fun( f:Int => Int ): Int = {f(20)}println(fun((x:Int)=>{x * 10}))println(fun((x)=>{x * 10}))println(fun((x)=>x * 10))println(fun(x=>x * 10))println(fun(_ * 10))}
}

5 闭包

闭包:如果一个函数,访问到了它的外部(局部)变量的值,那么这个函数和他所处的环境,称为闭包

object Test_High_Fun {def main(args: Array[String]): Unit = {// addX 函数接受一个整数参数 x,并返回一个函数,// 该函数接受一个整数参数 y,并返回 x + y 的结果。// 然后,我们通过调用 addX(5) 来创建一个新函数 addFive,它将 5 作为 x 的值。// 最后,我们调用 addFive(3),它返回 8,因为 5 + 3 = 8。def addX(x: Int) = (y: Int) => x + yval addFive = addX(5)println(addFive(3)) // 8}
}

6 函数柯里化

函数柯里化:把一个参数列表的多个参数,变成多个参数列表。

package com.mingyu.spark.core.testobject Test_High_Fun {def main(args: Array[String]): Unit = {//def add(x: Int, y: Int) = x + y//println(add(1, 2)) // 输出 3// 现在,我们可以使用函数柯里化来将 add 函数转换为一系列只接受单个参数的函数:def add(x: Int) = (y: Int) => x + yval addOne = add(1)println(addOne(2)) // 输出 3"""|在这个例子中,add 函数接受一个整数参数 x,并返回一个函数,|该函数接受一个整数参数 y,并返回 x + y 的结果。|然后,我们通过调用 add(1) 来创建一个新函数 addOne,它将 1 作为 x 的值。|最后,我们调用 addOne(2),它返回 3,因为 1 + 2 = 3。||通过函数柯里化,我们可以轻松地创建新的函数,例如 addTwo、addThree 等,|它们分别将 2 和 3 作为 x 的值,并接受单个整数参数 y。|这使得我们可以更容易地组合这些函数,并创建更复杂的函数,例如将它们作为参数传递给其他函数。""".stripMargin}
}

7 递归

package com.mingyu.spark.core.testobject Test_High_Fun {def main(args: Array[String]): Unit = {def fibo(n: Int): Int = {if (n > 2) return fibo(n - 1) + fibo(n - 2)else if (n == 2) return 1else return 0}//println(fibo(3))for (elem <- 1 to 10) print(fibo(elem) + "\t")}
}
// 0	1	1	2	3	5	8	13	21	34	

8 控制抽象

package com.mingyu.spark.core.testobject Test_High_Fun {def main(args: Array[String]): Unit = {"""|在Scala中,控制抽象是一种将控制流作为函数参数传递的技术。|换句话说,控制抽象允许我们将一些代码块作为参数传递给函数,并在函数内部执行这些代码块。|这使得我们可以编写更加灵活和可复用的代码。||Scala中的控制抽象通常使用高阶函数和函数字面量实现。|高阶函数是一个接受一个或多个函数作为参数的函数,而函数字面量是一个匿名函数,|它可以在任何需要函数的地方使用。||Scala中的控制抽象通常用于实现以下功能:||延迟计算:控制抽象可以用于延迟计算,即只有在需要的时候才计算某个值。例如,lazy 关键字就是一种控制抽象,它允许我们延迟计算某个值,直到我们需要使用它。|错误处理:控制抽象可以用于错误处理,例如使用 try 和 catch 块捕获异常。|并发编程:控制抽象可以用于并发编程,例如使用 Future 和 Promise 实现异步计算""".stripMargin"""|repeat 函数接受一个整数参数 n 和一个函数字面量 f,|并在函数内部执行 f 函数 n 次。""".stripMargindef repeat(n: Int)(f: => Unit): Unit = {for (i <- 1 to n) f}//  调用 repeat(5) 来创建一个新函数,并将一个打印语句作为 f 函数的参数val f2 = repeat(5) {println("hello")}// 用这个新函数,它将打印语句执行了 5 次f2}
}

 (Scala语言真的好奇特😄😄)

9 惰性加载

package com.mingyu.spark.core.testobject Test_High_Fun {def main(args: Array[String]): Unit = {"""|在这个例子中,变量 y 的值是立即计算出来的,因为它是一个非惰性值。|而变量 z 的值需要计算 x 的值,因此在第一次访问 x 时,初始化代码块被执行,|输出了 "Initializing x"。然后,变量 z 的值被计算为 43。||惰性加载在 Scala 中还有许多其他的应用场景,例如:||惰性集合:Scala 中的集合类支持惰性加载,可以在需要时才计算集合中的元素。|   例如,Stream 就是一种惰性集合,它只会计算需要的元素,而不会一次性计算所有元素。|惰性参数:Scala 中的函数可以定义惰性参数,即只有在需要时才会计算参数的值。|   例如,可以使用 => 来定义惰性参数,例如 def f(x: => Int) = ...。|   |此外,|  在 Scala 中,惰性参数的值在被第一次访问后会被存放在一个临时变量中。|  这个临时变量只会在第一次访问时被计算,然后将计算结果保存在这个变量中,|  以后再次访问时直接返回这个变量的值,而不会重新计算。||具体来说,当我们在函数体内访问一个惰性参数时,Scala 会自动将这个参数转换成一个函数,|然后调用这个函数。这个函数只会在第一次调用时被计算,然后将计算结果保存在一个临时变量中。|以后再次调用这个函数时,直接返回这个临时变量的值,而不会重新计算。""".stripMarginlazy val x = {println("Initializing x")42}val y = 1 + 2println("y = " + y) // 输出 "y = 3""""|第一次调用x,输出:|Initializing x|z = 43""".stripMarginval z = x + 1println("z = " + z)"""|第二次调用x,输出|u = 43""".stripMarginval u = x + 1println("u = " + u)}
}

相关内容

热门资讯

湾财周报|大事记 比亚迪驳斥“... 一周大事记(5月26日-6月1日) 头条 比亚迪驳斥! 长城“车圈恒大论”是行业警示还是危言耸听?...
通源石油跌1.96%,成交额1... 5月30日,通源石油跌1.96%,成交额1.03亿元,换手率4.40%,总市值23.54亿元。 异动...
中国邮储银行浙江分行2025校... 点这里 ↑ 老满说高考 作者 l 老满 生涯规划师l 升学顾问l 拆书家 这是 老满说高考公众号 的...
公募基金规模首次突破33万亿元... 每经记者:肖芮冬 每经编辑:叶峰 天赐良基日报第654期 一、今日基金新闻速览 1、华润元大基金贾...
湾财周报 大事记 比亚迪驳斥“... 一周大事记(5月26日-6月1日)头条比亚迪驳斥!长城“车圈恒大论”是行业警示还是危言耸听?近日,关...
EL表达式JSTL标签库 EL表达式     EL:Expression Language 表达式语言     ...
关于测试,我发现了哪些新大陆 关于测试 平常也只是听说过一些关于测试的术语,但并没有使用过测试工具。偶然看到编程老师...
工信部、中汽协紧急发声!汽车“... 文/刘育英新一轮汽车价格战再起。近日,工信部、中汽协纷纷发声表示反对。工业和信息化部表示,将加大对汽...
3 ROS1通讯编程提高(1) 3 ROS1通讯编程提高3.1 使用VS Code编译ROS13.1.1 VS Code的安装和配置...
募资39亿,全亏光了,账上不到... 关于天然气,用户的感觉是价格一直在上涨,但很奇怪,不管怎么涨,天然气企业仍然亏,还亏得一塌糊涂。这是...
资阳房产评估公司 这是(tel-15828298733)整理的信息,希望能帮助到大家 在当今社会,随着经济的发展和城...
华桥汇利(中国)投资基金管理有... 今年第一季度,美国企业利润出现大幅下降,且面临着来自关税上升的持续压力,这一局面可能会在今年进一步加...
ESG 报告合规与鉴证:全球政... 在当下全球经济格局里,ESG(环境、社会和公司治理)已然成为衡量企业可持续发展能力的关键指标。随着全...
【Unity 手写PBR】Bu... 写在前面 前期积累: GAMES101作业7提高-实现微表面模型你需要了解的知识 【技...
与锤巨子生物的大嘴博士持股同一... 医美龙头巨子生物“成分争议”风波持续发酵。日前,美妆博主大嘴博士(香港大学化学博士郝宇)发文,质疑巨...
Linux之进程间通信 目录 进程间通信介绍 一、为什么要进行进程间通信? 二、进程间通信目的 三、进程间通信...
从“造城”到“留客”,文旅局长... 你有没有刷到最近各地文旅局局长全体“尬舞”的视频?领导们放下架子开始跳魔性舞蹈,这场舞的背后啊,可不...
Hazel引擎学习(十一) 我自己维护引擎的github地址在这里,里面加了不少注释,有需要的可以看...
孩子的教育金,分享3个「有效」... 点击 “简七读财” ,发送消息“ 理财小工具 ”免费领取“40个赚钱工具资源包”晚上好,我是简七编...
iZotope RX 10(专... iZotope RX 10是一款专业的音频修复和增强软件,具有音频修复工具、音频增强工...
我的docker随笔40:cl... 本文介绍 clickhouse 数据库的容器化部署。 起因 某项目需生产环境数据库,因...
透视一周牛熊股:最牛股路桥信息... 过去一周(5月26日—5月30日)A股三大指数集体下跌。截至5月30日收盘,上证指数报3347.49...
基于matlab创建地面固定雷... 一、前言此示例演示如何创建和显示包含地面固定雷达、转弯飞机、等速飞机和移动地面车辆的多平台方案。二、...
暗夜发光,独自闪耀,盘点网页暗... 众所周知,网页的暗黑模式可以减少屏幕反射和蓝光辐射,减少眼睛的疲劳感&#...
C语言-程序环境和预处理(2) 文章目录预处理详解1.预定义符号2.#define2.1#define定义的标识符2.2#defin...
MySQL数据库知识整理 MySQL数据库知识整理 MySQL事务详解 事务四大特性ACID 原子性(Atomi...
Docker基础篇——最全讲解 文章目录一、CentOS安装docker二、启动帮助类命令三、镜像命令1.名词概念2.常用命令2.1...
五问“恒大论”,比亚迪回应车圈... “车圈恒大”引发的舆论风暴还在进一步发酵。近日,比亚迪集团品牌及公关处总经理李云飞在微博发文,引用多...
javafx实现聚光灯效果,圆... 系列文章专栏:javafx图形绘制、桌面录屏录音源码合集 目录 一、实现的效果 二、实现思路
300左右哪款蓝牙耳机适合学生... 近年来,随着蓝牙耳机的发展,不管是音质、外观、佩戴还是降噪都有了很大的提...