`
zhangxiong0301
  • 浏览: 350688 次
社区版块
存档分类
最新评论

case语句和偏函数

 
阅读更多

Scala通过case语句提供了形式简单、功能强大的模式匹配功能。但是也许你不知道,Scala还具有一个与case语句相关的语言特性,那就是:在Scala中,被“{}”包含的一系列case语句可以被看成是一个函数字面量,它可以被用在任何普通的函数字面量适用的地方,例如被当做参数传递。 

Scala代码  收藏代码
  1. scala> val defaultValue:Option[Int] => Int = {  
  2. case  Some(x) => x  
  3. case None => 0                                }                                                                      
  4. scala> defaultValue(Some(5))                         
  5. res1: Int = 5                     


defaultValue是一个函数字面量,它的值是: 

Scala代码  收藏代码
  1. {  
  2.   case  Some(x) => x  
  3.   case None => 0                                 
  4. }                        


看懂了以上的代码,我们就不难理解在Scala的Actor中经常使用的react函数的语法形式: 

Scala代码  收藏代码
  1. react {  
  2. case (name: String, actor: Actor) => {  
  3.   actor ! getip(name)  
  4.   act()  
  5. }  
  6. case msg => {  
  7.   println("Unhandled message: "+ msg)  
  8.   act()  
  9. }  
  10. }  


react是一个函数,它接收一个函数字面量作为参数。至此我们都没有提到偏函数的概念。什么是偏函数?它与Case语句有什么关系? 

在Scala中,偏函数是具有类型PartialFunction[-A,+B]的一种函数。A是其接受的函数类型,B是其返回的结果类型。偏函数最大的特点就是它只接受和处理其参数定义域的一个子集,而对于这个子集之外的参数则抛出运行时异常。这与Case语句的特性非常契合,因为我们在使用case语句是,常常是匹配一组具体的模式,最后用“_”来代表剩余的模式。如果一一组case语句没有涵盖所有的情况,那么这组case语句就可以被看做是一个偏函数。 

case语句作为偏函数字面量: 

Scala代码  收藏代码
  1. val second:PartialFunction[List[Int],Int] = {  
  2.     case List(x::y::_) => y  
  3. }  


second函数的功能是返回一个List[Int]中的第二个值。case函数体只涵盖了当一个List的长度大于2的情况,而忽略Nil和长度为1的列表。 

Scala代码  收藏代码
  1. scala.MatchError: List(2)  
  2.         at $anonfun$1.apply(<console>:9)  
  3.         at $anonfun$1.apply(<console>:9)  
  4.         at .<init>(<console>:11)  
  5.         at .<clinit>(<console>)  
  6.         at RequestResult$.<init>(<console>:9)  
  7.         at RequestResult$.<clinit>(<console>)  
  8.         at RequestResult$scala_repl_result(<console>)  
  9.         at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)  
  10.         at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)  
  11.         at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)  
  12.         at java.lang.reflect.Method.invoke(Method.java:597)  
  13.         at scala.tools.nsc.Interpreter$Request$$anonfun$loadAndRun$1$$anonfun$apply$18.apply(Interpreter.scala:981)  
  14.         at scala.tools.nsc.Interpreter$Request$$anonfun$loadAndRun$1$$anonfun$apply$18.apply(Interpreter.scala:981)  
  15.         at scala.util.contr...  
  16.   
  17. scala> second(1::2::Nil)  
  18. res8: Int = 2  


当我们试图传入一个不在偏函数的定义域范围内的参数时,抛出了异常。如果我们想在调用函数前先检查一个参数是否在定义域范围以避免抛出异常,那么可以使用偏函数的isDefinedAt方法。 

Scala代码  收藏代码
  1. scala> second.isDefinedAt(List(2,3,4))  
  2. res10: Boolean = true  


实际上,scala编译器把函数字面量: 

Scala代码  收藏代码
  1. {  
  2.     case List(x::y::_) => y  
  3. }  


编译成了如下的等价形式: 

Scala代码  收藏代码
  1. new PartialFunction[List[Int], Int] {  
  2. def apply(xs: List[Int]) = xs match {  
  3. case x :: y :: _ => y  
  4. }  
  5. def isDefinedAt(xs: List[Int]) = xs match {  
  6. case x :: y :: _ => true  
  7. case _ => false  
  8. }  
  9. }  


这种转换是一种编译期行为,我们必须把second显式的声明为PartialFunction类型,如果没有给second指定类型,那么scala编译器会把后面的一组case语句编译成Function1类型,即完整的函数。 

Tips:一组case语句要成为一个偏函数,那么它被赋予的变量必须被声明为PartionFunction[-A,+B] 

那么我们什么时候该使用偏函数?或者说偏函数给我们带来了什么好处?当我们确定我们的程序不会被传入不可处理的值时,我们就可以使用偏函数。这样万一程序被传入了不应该被传入的值,程序自动抛出异常,而不需要我们手工编写代码去抛出异常,减少了我们的代码量。

分享到:
评论

相关推荐

    用函数指针替代Switch/Case语句的程序设计方法

    单片机程序中,当Switch/Case语句分支较多、处理代码较长、处理情况较为复杂时,逻辑修改和程序调试均存在一定的困难。针对该问题,本文给出了使用函数指针替代Switch/Case语句的实现思路以及相对应的代码模型,为...

    mysql存储过程之case语句用法实例详解

    mysql的 CASE语句使代码更加可读和高效。废话不多说,我们先来看下简单case语句的语法: CASE case_expression WHEN when_expression_1 THEN commands WHEN when_expression_2 THEN commands ... ELSE ...

    Oracle-Decode()函数和CASE语句的比较

    本文讲述了Oracle-Decode()函数和CASE语句的比较。

    5.3: case语句 、 函数及中断控制 、 字符串处理 、 总结和答疑.docx

    5.3: case语句 、 函数及中断控制 、 字符串处理 、 总结和答疑.docx

    基于C语言实现switch case语句(源码)

    使用switch case语句根据不同的成绩等级进行匹配和输出相应的评价。在这里,使用了case语句的多值匹配,例如'A'和'a'都会输出"Excellent!"。 如果用户输入的成绩等级不在'A'、'B'、'C'、'D'、'F'范围内,则执行...

    scala的偏函数

    偏函数被包在花括号内没有match的一组case语句是一个偏函数 偏函数是PartialFunction[A, B]的一个实例 A代表输入参数类型 B代表返回结果类型 示例一 示例说明 定义一个偏函数,根据以下方式返回 参考代码 // func1...

    MATLAB中的switch-case判断语句与for循环语句.md

    源代码中展示了函数的实现过程,包括使用`for`循环迭代处理包含数字的向量,并结合`switch-case`语句根据数字的值输出对应的英文单词。文档还演示了如何使用该函数,并给出了一个输出数字对应英文单词的示例。希望这...

    Linux运维-运维系统服务04-Shell脚本d6-Shell函数与正则表达式-04case语句基本语法结构1.mp4

    Linux运维-运维系统服务04-Shell脚本d6-Shell函数与正则表达式-04case语句基本语法结构

    Linux运维-运维系统服务04-Shell脚本d6-Shell函数与正则表达式-05case语句基本语法结构2.mp4

    Linux运维-运维系统服务04-Shell脚本d6-Shell函数与正则表达式-05case语句基本语法结构

    SQL Server高级内容之case语法函数概述及使用

    1.Case函数的用法 (1)使用类似:switch-case与if-else if。 (2)语法: case [字段] when 表达式 then 显示数据 when 表达式 then 显示数据 else 显示数据 end (3)百分制转换素质教育 1)如图:我们要将显示的数据...

    sql中case语句的用法浅谈

    简单Case函数和Case搜索函数。 代码如下:–简单Case函数 CASE sex  WHEN ‘1’ THEN ‘男’  WHEN ‘2’ THEN ‘女’ ELSE ‘其他’ END –Case搜索函数 CASE WHEN sex = ‘1’ THEN ‘男’  WHEN sex = ‘2’ ...

    oracle case when 语句的用法详解

    1. CASE WHEN 表达式有两种形式 代码如下:–简单Case函数 CASE sex WHEN ‘1’ THEN ‘男’ WHEN ‘2’ THEN ‘女’ ELSE ‘其他’ END –Case搜索函数 CASEWHEN sex = ‘1’ THEN ‘男’ WHEN sex = ‘2’ ...

    switch函数使用示例

    switch函数是JavaScript中的一种条件语句,用于根据不同的条件...如果匹配成功,则执行该case语句后面的代码块,直到遇到break语句或switch语句结束。如果没有匹配成功的case语句,则执行default后面的代码块(可选)。

    greenplum常用函数-基础

    gp常用的建表语句,修改新增字段等常见操作,以及时间函数转换和case,基本函数使用,和具体表中遇到的问题。 ps:借用了其他同学的部分总结

    Shell编程之case语句实战(小结)

    其实case语句还是很好理解的,在shell编程中,if语句有它的语法,函数也有它的语法,那么在我们shell编程中的case语句也是有它的语法的,如下: case 变量名 in 值1) 指令1 ;; 值2) 指令2 ;; 值3) 指令3 ;...

    switch语句的妙用(必看篇)

    这里a和case列表中从上而下逐一做比较,如果匹配就执行case中的代码,若有break则跳出,无break则继续往下匹配,直到新的匹配和break或switch代码块结束。 注意: a和case值的匹配算法是执行严格相等比较的(‘===’...

    MySQL中的if和case语句使用总结

    Mysql的if既可以作为表达式用,也可在存储过程中作为流程控制语句使用,如下是做为表达式使用: IF表达式 代码如下: IF(expr1,expr2,expr3) 如果 expr1 是TRUE (expr1 &lt;&gt; 0 and expr1 &lt;&gt; NULL),则 IF()的...

    MySQL 的CASE WHEN 语句使用说明

    mysql数据库中CASE WHEN语句。 case when语句,用于计算条件列表并返回多个可能结果表达式之一。 CASE 具有两种格式: 简单 CASE 函数将某个表达式与一组简单表达式进行比较以确定结果。 CASE 搜索函数计算一组布尔...

    python中Switch/Case实现的示例代码

    学习Python过程中,发现没有switch-case,过去写C习惯用Switch/Case语句,官方文档说通过if-elif实现。所以不妨自己来实现Switch/Case功能。 使用if…elif…elif…else 实现switch/case 可以使用if…elif…elif.....

Global site tag (gtag.js) - Google Analytics