Scala学习笔记(六) Scala的偏函数和偏应用函数

简介: Scala学习笔记(六) Scala的偏函数和偏应用函数

1. 偏函数



偏函数(Partial Function),是一个数学概念它不是"函数"的一种, 它跟函数是平行的概念。


Scala中的Partia Function是一个Trait,其的类型为PartialFunction[A,B],其中接收一个类型为A的参数,返回一个类型为B的结果。


举个例子

scala> val pf:PartialFunction[Int,String] = {
     |   case 1=>"One"
     |   case 2=>"Two"
     |   case 3=>"Three"
     |   case _=>"Other"
     | }
pf: PartialFunction[Int,String] = <function1>
scala> pf(1)
res0: String = One
scala> pf(2)
res1: String = Two
scala> pf(3)
res2: String = Three
scala> pf(4)
res3: String = Other


偏函数内部有一些方法,比如isDefinedAt、OrElse、 andThen、applyOrElse等等。


1.1 isDefinedAt


isDefinedAt : 这个函数的作用是判断传入来的参数是否在这个偏函数所处理的范围内。

刚才定义的pf来尝试使用isDefinedAt(),只要是数字都是正确的,因为有case _=>"Other"这一句。如果换成其他类型就会报错。

scala> pf.isDefinedAt(1)
res4: Boolean = true
scala> pf.isDefinedAt(2)
res5: Boolean = true
scala> pf.isDefinedAt("1")
<console>:13: error: type mismatch;
 found   : String("1")
 required: Int
       pf.isDefinedAt("1")
                      ^
scala> pf.isDefinedAt(100)
res7: Boolean = true


那我们再定义一个PartialFunction

scala> val anotherPF:PartialFunction[Int,String] = {
     |    case 1=>"One"
     |    case 2=>"Two"
     |    case 3=>"Three"
     | }
anotherPF: PartialFunction[Int,String] = <function1>
scala> anotherPF.isDefinedAt(1)
res8: Boolean = true
scala> anotherPF.isDefinedAt(2)
res9: Boolean = true
scala> anotherPF.isDefinedAt(3)
res10: Boolean = true
scala> anotherPF.isDefinedAt(4)
res11: Boolean = false


去掉了原先的最后一句,再执行anotherPF.isDefinedAt(4)会返回false。


1.2 orElse


orElse : 将多个偏函数组合起来使用,效果类似case语句。

scala> val onePF:PartialFunction[Int,String] = {
     |   case 1=>"One"
     | }
onePF: PartialFunction[Int,String] = <function1>
scala> val twoPF:PartialFunction[Int,String] = {
     |   case 2=>"Two"
     | }
twoPF: PartialFunction[Int,String] = <function1>
scala> val threePF:PartialFunction[Int,String] = {
     |   case 3=>"Three"
     | }
threePF: PartialFunction[Int,String] = <function1>
scala> val otherPF:PartialFunction[Int,String] = {
     |   case _=>"Other"
     | }
otherPF: PartialFunction[Int,String] = <function1>
scala> val newPF = onePF orElse twoPF orElse threePF orElse otherPF
newPF: PartialFunction[Int,String] = <function1>
scala> newPF(1)
res0: String = One
scala> newPF(2)
res1: String = Two
scala> newPF(3)
res2: String = Three
scala> newPF(4)
res3: String = Other


这样,newPF跟原先的pf效果是一样的。


1.3 andThen


andThen: 相当于方法的连续调用,比如g(f(x))。

scala> val pf1:PartialFunction[Int,String] = {
     |   case i if i == 1 => "One"
     | }
pf1: PartialFunction[Int,String] = <function1>
scala> val pf2:PartialFunction[String,String] = {
     |   case str if str eq "One" => "The num is 1"
     | }
pf2: PartialFunction[String,String] = <function1>
scala> val num = pf1 andThen pf2
num: PartialFunction[Int,String] = <function1>
scala> num(1)
res4: String = The num is 1


pf1的结果返回类型必须和pf2的参数传入类型必须一致,否则会报错。


1.4 applyOrElse


applyOrElse:它接收2个参数,第一个是调用的参数,第二个是个回调函数。如果第一个调用的参数匹配,返回匹配的值,否则调用回调函数。

scala> onePF.applyOrElse(1,{num:Int=>"two"})
res5: String = One
scala> onePF.applyOrElse(2,{num:Int=>"two"})
res6: String = two


在这个例子中,第一次onePF匹配了1成功则返回的是"One"字符串。第二次onePF匹配2失败则触发回调函数,返回的是"Two"字符串。


2. 偏应用函数



偏应用函数(Partial Applied Function)也叫部分应用函数,跟偏函数(Partial Function)从英文名来看只有一字之差,但他们二者之间却有天壤之别。


部分应用函数, 是指一个函数有n个参数, 而我们为其提供少于n个参数, 那就得到了一个部分应用函数。


个人理解的偏应用函数类似于柯里化,可以参考我以前写的文章借助Java 8实现柯里化

举个例子,定义好一个函数有3个参数,再提供几个有1-2个已知参数的偏应用函数

scala> def add(x:Int,y:Int,z:Int) = x+y+z
add: (x: Int, y: Int, z: Int)Int
scala> def addX = add(1,_:Int,_:Int) // x 已知
addX: (Int, Int) => Int
scala> addX(2,3)
res1: Int = 6
scala> addX(3,4)
res2: Int = 8
scala> def addXAndY = add(10,100,_:Int) // x 和 y 已知
addXAndY: Int => Int
scala> addXAndY(1)
res3: Int = 111
scala> def addZ = add(_:Int,_:Int,10) // z 已知
addZ: (Int, Int) => Int
scala> addZ(1,2)
res4: Int = 13


总结



本篇笔记是为了下一篇 Scala 模式匹配所做的铺垫。模式匹配会用到偏函数,所以先整理出来。还详细介绍了偏函数和偏应用函数的区别。

相关文章
|
7月前
|
分布式计算 Scala Spark
Scala【集合常用方法和函数操作(下)】
Scala【集合常用方法和函数操作(下)】
|
7月前
|
分布式计算 Scala Spark
Scala 【集合常用方法和函数操作-上】
Scala 【集合常用方法和函数操作-上】
|
1月前
|
Java Scala
Scala 方法与函数
Scala 方法与函数
23 1
|
7月前
|
SQL Java 关系型数据库
Scala应用 —— JDBC的创建
这篇文章介绍了如何使用Scala实现JDBC连接。首先,通过在pom.xml添加MySQL JDBC驱动依赖,然后使用`Class.forName()`加载驱动,接着创建连接对象。初始化执行器涉及创建执行器对象和设置参数。执行操作时,根据DML(数据修改语言)和DQL(数据查询语言)返回不同结果。文章提出了一个柯里化的`jdbc`函数,以处理不同操作步骤和多类型结果。结果类型通过枚举和抽象类`Three`的子类来表示,包括异常、DML影响行数和DQL查询结果。最后,展示了`jdbc`方法的实现,以及如何处理结果并转换为具体对象。代码示例中,查询结果被转换为`Test`对象数组并打印。
100 2
Scala应用 —— JDBC的创建
|
7月前
|
数据采集 JSON 数据处理
一步步实现知乎热榜采集:Scala与Sttp库的应用
使用Scala和Sttp库,结合代理IP,本文阐述了爬取并处理知乎热榜数据的方法。首先,确保安装Scala和SBT,然后在`build.sbt`引入Sttp等相关依赖。代码中,设置代理服务器信息、User-Agent和Cookie,发送GET请求获取数据。解析JSON数据后,归类和统计不同类型条目的数量,例如文章和问题。运行示例输出归类和统计结果,为数据分析提供基础。
一步步实现知乎热榜采集:Scala与Sttp库的应用
|
6月前
|
Scala
scala-模式匹配(字符串、数组、元组、集合、类、偏函数)
scala-模式匹配(字符串、数组、元组、集合、类、偏函数)
31 0
|
7月前
|
编译器 Scala
认识scala中的函数
认识scala中的函数
68 5
|
7月前
|
Scala
Scala函数和方法
Scala函数和方法
40 1
|
7月前
|
分布式计算 Java 大数据
Scala:样例类、模式匹配、Option、偏函数、泛型(三)
Scala:样例类、模式匹配、Option、偏函数、泛型(三)
84 0
|
机器学习/深度学习 分布式计算 Java
Scala方法和函数
Scala方法和函数
105 0