如果你想定义一个函数,而让它只接受和处理其参数定义域范围内的子集,对于这个参数范围外的参数则抛出异常,这样的函数就是偏函数(顾名思异就是这个函数只处理传入来的部分参数)。

偏函数是个特质其的类型为PartialFunction[A,B],其中接收一个类型为A的参数,返回一个类型为B的结果。
其有个重要的函数就是:
1
def isDefinedAt(x: A): Boolean //作用是判断传入来的参数是否在这个偏函数所处理的范围内
定义一个普通的除法函数:

1
2
3
4
5
scala> val divide = (x : Int) => 100/x
divide: Int => Int = <function1>
输入参数0
scala> divide(0)
java.lang.ArithmeticException: / by zero 
显然,当我们将0作为参数传入时会报错,一般的解决办法就是使用try/catch来捕捉异常或者对参数进行判断看其是否等于0;但是在Scala的偏函数中这些都已经封装好了,如下:将divide定义成一个偏函数()
1
2
3
4
val divide = new PartialFunction[Int,Int] {
def isDefinedAt(x: Int): Boolean = x != 0 //判断x是否等于0,当x = 0时抛出异常
def apply(x: Int): Int = 100/x
}  
但是,当偏函数与case语句结合起来就能使代码更简洁,如下:
1
2
3
val divide1 : PartialFunction[Int,Int] = {
case d : Int if d != 0 => 100/d //功能和上面的代码一样,这就是偏函数的强大之处,方便,简洁!!
} 
其实这代码就是对上面那段代码的封装,这里同样调用isDefinedAt方法
1
2
3
4
5
scala> divide1.isDefinedAt(0)
res1: Boolean = false
  
scala> divide1.isDefinedAt(10)
res2: Boolean = true 
再举个与case结合使用的例子:
1
2
3
4
5
val rs : PartialFunction[Int , String] = {
case 1 => "One"
case 2 => "Two"
case _ => "Other"
}
输入:
1
2
3
4
5
6
7
8
scala> rs(1)
res4: String = One
  
scala> rs(2)
res5: String = Two
  
scala> rs(100)
res6: String = Other
 
OrElse
OrElse方法可以将多个偏函数组合起来使用,结合起来的效果类似case语句,但是每个偏函数里又可以再使用case
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
scala> val or1 : PartialFunction[Int,String] = {case 1 => "One"}
or1: PartialFunction[Int,String] = <function1>
  
scala> val or2 : PartialFunction[Int,String] = {case 2 => "Two"}
or2: PartialFunction[Int,String] = <function1>
  
scala> val or_ : PartialFunction[Int,String] = {case _ => "Other"}
or_: PartialFunction[Int,String] = <function1>
  
scala> val or = or1 orElse or2 orElse or_ //使用orElse将多个偏结合起来
or: PartialFunction[Int,String] = <function1>
  
scala> or(1)
res7: String = One
  
scala> or(20)
res9: String = Other
orElse还可以直接连接case使用
1
2
3
4
5
6
7
8
9
scala> val orCase:(Int => String) = or1 orElse {case _ => "Other"}
orCase: Int => String = <function1>
  
scala> orCase(1)
res10: String = One
  
scala> orCase(10)
res11: String = Other
   
 
andThen
对函数的结果进行下一步的处理
1
2
3
4
5
6
7
8
9
10
11
scala> val at1 : PartialFunction[Int,String] = {case cs if cs == 1 => "One"}
at1: PartialFunction[Int,String] = <function1>
  
scala> val at2 : PartialFunction[String,String] = {case cs if cs eq "One" => "The num is 1"}
at2: PartialFunction[String,String] = <function1>
  
scala> val num = at1 andThen at2
num: PartialFunction[Int,String] = <function1>
  
scala> num(1)
res18: String = The num is 1
 
注意:at1函数的结果返回类型必须和at2函数的参数传入类型一致,不然会编译报错

Partial Functions(偏函数)的更多相关文章

  1. Python partial function 偏函数

    Partial function 偏函数是将所要承载的函数作为partial()函数的第一个参数,原函数的各个参数依次作为partial()函数后续的参数,除非使用关键字参数. 当函数的参数个数太多, ...

  2. Python使用functools模块中的partial函数生成偏函数

    所谓偏函数即是规定了固定参数的函数,在函数式编程中我们经常可以用到,这里我们就来看一下Python使用functools模块中的partial函数生成偏函数的方法 python 中提供一种用于对函数固 ...

  3. Scala-Partial Functions(偏函数)

    如果你想定义一个函数,而让它只接受和处理其参数定义域范围内的子集,对于这个参数范围外的参数则抛出异常,这样的函数就是偏函数(顾名思异就是这个函数只处理传入来的部分参数). 偏函数是个特质其的类型为Pa ...

  4. Scala方法定义,方法和函数的区别,将方法转换成函数

    1. 定义方法和函数 1.1. 定义方法 方法的返回值类型可以不写,编译器可以自动推断出来,但是对于递归函数,必须指定返回类型 1.2. 定义函数 1.3.方法和函数的区别 在函数式编程语言中,函数是 ...

  5. python3 第二十三章 - 函数式编程之Partial function(偏函数)

    要注意,这里的偏函数和数学意义上的偏函数不一样,偏函数是2.5版本以后引进来的东西,属于函数式编程的一部分.前面章节中我们讲到,通过设定参数的默认值,可以降低函数调用的难度.而偏函数也可以做到这一点. ...

  6. python reduce和偏函数partial

    functools模块 reduce方法: reduce方法 reduce方法,顾名思义就是减少 可迭代对象不能为空,初始值没提供就在可迭代对象中去一个元素 from functools import ...

  7. iter的特殊用法以及偏函数partial

    iter()的特殊用法 常规使用 iter(obj),会返现一个迭代器,如果 obj 不是可迭代对象,则会报错. 特殊用法(哨兵模式) iter(object[, sentinel]) sentine ...

  8. JavaScript中的Partial Application和Currying

    这篇文章是一篇学习笔记,记录我在JS学习中的一个知识点及我对它的理解,知识点和技巧本身并不是我原创的.(引用或参考到的文章来源在文末) 先不解释Partial Application(偏函数应用)和C ...

  9. python 全栈开发,Day116(可迭代对象,type创建动态类,偏函数,面向对象的封装,获取外键数据,组合搜索,领域驱动设计(DDD))

    昨日内容回顾 1. 三个类 ChangeList,封装列表页面需要的所有数据. StarkConfig,生成URL和视图对应关系 + 默认配置 AdminSite,用于保存 数据库类 和 处理该类的对 ...

随机推荐

  1. springmvc之获取参数

    1.导包,四大核心包,一个切面包(AOP),logging,web,springmvc 2.配置文件,核心代码如下: web.xml <servlet> <servlet-name& ...

  2. centos 安装 Splunk

    (1).需关闭selinux: 1. vi /etc/sysconfig/selinux    SELINUX=disabled (2).开始安装mkdir  \splunk http://downl ...

  3. 018:InnoDB 存储引擎、表空间

    目录 一.InnoDB 存储引擎 1. InnoDB的历史 2. InnoDB的特点 3. InnoDB存储引擎的文件 3.1 概述 3.2 InnoDB - 表空间 3.3 General表空间 3 ...

  4. MySql——事务控制语言(DTL)

    什么是事务(控制台只能是内存的操作) 通常,在此之前,我们说,一条语句使用一个分号(;)来结束,并得到执行. 那么我们说,这个“一次性执行”的过程,可以称为“一个事务”. 简单来说,“一条sql语句, ...

  5. kafka的OffsetOutOfRangeError

    from kafka import KafkaClient, SimpleConsumer from sys import argv kafka = KafkaClient("10.0.1. ...

  6. SharePoint 事件 7363:对象缓存:缓存使用的超级读者帐户没有足够的权限访问SharePoint数据库。

    转自MSND:http://technet.microsoft.com/zh-cn/library/ff758656(v=office.14) 对象缓存存储 Microsoft SharePoint ...

  7. Django models拆分

    大多数Django教程都是将models放在models.py文件(模块)中, 然而随着models类的增加, 将类放在一个文件中太混乱了, 于是将models做成一个package: 这样就可以将m ...

  8. IOS Background 之 Background Fetch

    http://www.ithao123.cn/content-1363653.html 定期更新数据的app,比如及时通信类,微博等app. 定期后台获取,等打开后获取的快一些. 30分钟后打开手,获 ...

  9. MySQL修改redo_log_size

    MySQL5.5 步骤如下: 1. set global innodb_fast_shutdown = 0; 2. mysqladmin shutdown 3. 修改my.cnf innodb_log ...

  10. C++Primer笔记-----day03

    ==============================================================day03================================= ...