美文网首页首页投稿(暂停使用,暂停投稿)
Scala的柯里化和函数的部分施用

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

作者: 每天学点编程 | 来源:发表于2017-10-03 15:35 被阅读264次

    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语法有着额外的好处。

    mapcollect的区别:

    无法顺利地在一个混杂不同类型元素的集合上执行带着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语言中的偏函数和部分施用函数英文原名比较接近,但以功能来说,它们根本就不在一个维度上。如果有需要的话,完全可以对一个偏函数进行部分施用。

    相关文章

      网友评论

        本文标题:Scala的柯里化和函数的部分施用

        本文链接:https://www.haomeiwen.com/subject/ownoextx.html