Scala支持柯里化和部分施用,另外还有一个用来定义偏函数的trait
。
柯里化
Scala允许函数定义多组参数列表,每组写在一对圆括号里。当用少于定义数目的参数来调用函数的时候,将返回一个以余下的参数列表为参数的函数。
filter()
函数递归地执行传入的筛选条件。筛选条件modN()
函数定义了两组参数列表,而filter()
调用它的时候,只传入了一个参数。作为modN()
柯里化的结果,得到一个参数为Int
类型并返回Boolean类型的函数,正好符合filter()
函数定义中对其第二个参数的要求。
部分施用函数——实例
首先定义了从货品映射到价格的price()
函数。接着又定义了以价格和所属州为参数计算税后价的withTax()
函数。
偏函数
Scala设计出PartialFunction trait是为了密切配合语言中的模式匹配特性。尽管名称相似,PartialFunction trait并不生成部分施用函数。它的真正用途是描述只对定义域中一部分取值或类型有意义的函数。
Case
语句是偏函数的一种用法。下面的Scala代码单独使用了case
关键字,没有出现习惯上总是和case
搭配在一起的match
。
不和match一起出现的case:
先创建了反映城市与所属州对应关系的一个
Map
。然后在集合上调用map()
函数,把键值对的内容逐一拆开并打印出来。在Scala语言里,含有case
语句的代码块是匿名函数的一种定义方式。不带上case
,可以写出更加简练的匿名函数定义,但case
语法有着额外的好处。
map
和collect
的区别:
无法顺利地在一个混杂不同类型元素的集合上执行带着case
匿名函数的map
操作:当函数企图对"seven"字符串做算术递增的时候,运行时得到MatchError
。可是另一行的collect()
操作就能正确执行完。
Case语句定义了偏函数(partial function),请注意不要和名称相近的部分施用函数相混淆。偏函数的参数被限定了取值范围。偏函数提供了一种对参数取值设置约束条件的途径。上例中在执行collect()
操作时,取值条件是为Int
而设的,String
类型不包括在内,所以字符串"seven
"没有被采集。
偏函数——直接使用PartialFunction trait来定义偏函数
从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语言中的偏函数和部分施用函数英文原名比较接近,但以功能来说,它们根本就不在一个维度上。如果有需要的话,完全可以对一个偏函数进行部分施用。
网友评论