Scala的柯里化和函数的部分施用

Posted 从头开始自学java

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Scala的柯里化和函数的部分施用相关的知识,希望对你有一定的参考价值。

柯里化

Scala允许函数定义多组参数列表,每组写在一对圆括号里。当用少于定义数目的参数来调用函数的时候,将返回一个以余下的参数列表为参数的函数。



filter()函数递归地执行传入的筛选条件。筛选条件modN()函数定义了两组参数列表,而filter()调用它的时候,只传入了一个参数。作为modN()柯里化的结果,得到一个参数为Int类型并返回Boolean类型的函数,正好符合filter()函数定义中对其第二个参数的要求。


部分施用函数——实例

Scala的柯里化和函数的部分施用

首先定义了从货品映射到价格的price()函数。接着又定义了以价格和所属州为参数计算税后价的withTax()函数。

偏函数

Scala设计出PartialFunction trait是为了密切配合语言中的模式匹配特性。尽管名称相似,PartialFunction trait并不生成部分施用函数。它的真正用途是描述只对定义域中一部分取值或类型有意义的函数。

Case语句是偏函数的一种用法。下面的Scala代码单独使用了case关键字,没有出现习惯上总是和case搭配在一起的match

不和match一起出现的case:


Scala的柯里化和函数的部分施用


先创建了反映城市与所属州对应关系的一个Map。然后在集合上调用map()函数,把键值对的内容逐一拆开并打印出来。在Scala语言里,含有case语句的代码块是匿名函数的一种定义方式。不带上case,可以写出更加简练的匿名函数定义,但case语法有着额外的好处。


mapcollect的区别:

Scala的柯里化和函数的部分施用

无法顺利地在一个混杂不同类型元素的集合上执行带着case匿名函数的map操作:当函数企图对"seven"字符串做算术递增的时候,运行时得到MatchError。可是另一行的collect()操作就能正确执行完。

Case语句定义了偏函数(partial function),请注意不要和名称相近的部分施用函数相混淆。偏函数的参数被限定了取值范围。偏函数提供了一种对参数取值设置约束条件的途径。上例中在执行collect()操作时,取值条件是为Int而设的,String类型不包括在内,所以字符串"seven"没有被采集。

偏函数——直接使用PartialFunction trait来定义偏函数

Scala的柯里化和函数的部分施用

PartialFunction trait派生出answerUnits,并实现了两个函数,apply()isDefinedAt()。其中apply()函数负责具体的运算。另一个方法isDefinedAt()是定义一个PartialFunction的硬性要求,在这里设置判断参数是否有效的约束条件。

Scala允许用case代码块来定义偏函数,answerUnits可以改成更加简练的写法:


联用case和防卫条件来共同限制参数的取值,并输出计算结果。两种写法有一处值得注意的区别,上例在除以0时得到的错误类型是MatchError,不同于前一个例子的ArithmeticException,这是该例使用了模式匹配。

偏函数——偏函数的使用范围不限于数值类型


定义的偏函数接受任何类型的输入(Any),但只对其中特定的部分类型作出反应。例中对该偏函数调用了isDefinedAt()来判断它的取值范围,这是由于以case代码块方式实现的PartialFunction trait都隐含地定义了isDefinedAt()方法。map()collect()的行为差异,可以从偏函数的行为得到解释:collect()在设计的时候就考虑到传入偏函数的情况,会调用isDefinedAt()函数来鉴别集合元素是否符合取值条件,不符合的就被忽略掉了。
Scala语言中的偏函数和部分施用函数英文原名比较接近,但以功能来说,它们根本就不在一个维度上。如果有需要的话,完全可以对一个偏函数进行部分施用。


以上是关于Scala的柯里化和函数的部分施用的主要内容,如果未能解决你的问题,请参考以下文章

Scala - 柯里化和默认参数

js 基础 源码学习 柯里化和箭头函数

js高阶函数应用—函数柯里化和反柯里化

[Scala函数特性系列]——部分应用函数和柯里化

scala函数,柯里化函数

scala高级函数快速掌握