`

scala pattern matching

 
阅读更多

scala pattern matching

pattern matching是用来检查一个值是否满足一个模式的机制。一个成功的匹配也可以解析出一个值变成它的组成部分(constituent parts)。这是一个比Java switch语句功能更强大的版本,它也同样能用在一系列if/else语句的地方。

语义Syntax

一个match表达式有一个值,一个match关键字和至少一个case语句。

import scala.util.Random

val x: Int = Random.nextInt(10)

x match {
  case 0 => "zero"
  case 1 => "one"
  case 2 => "two"
  case _ => "many"
}

 上面的val x是一个0到10之间的随机数。x变成match的左操作数,在右边是一个有四个case的表达式。最后一个case _ 是一个”捕获所有“的case,对于任意的大于2的数字。Cases也被称作选项。

 

Match表达式是有值的。

def matchTest(x: Int): String = x match {
  case 1 => "one"
  case 2 => "two"
  case _ => "many"
}
matchTest(3)  // many
matchTest(1)  // one

 这个match表达式有一个String类型,因为所有的case都返回String。因此,这个matchTest函数返回一个String。

匹配case class(Matching on case classes)

case class对于pattern matching特别有用。

abstract class Notification

case class Email(sender: String, title: String, body: String) extends Notification

case class SMS(caller: String, message: String) extends Notification

case class VoiceRecording(contactName: String, link: String) extends Notification

 Notification是一个抽象的超类,有三个具体的Notification类型,以case class Email,SMS和VoiceRecording来实现。现在我们可以在这些case class上进行pattern matching了。

def showNotification(notification: Notification): String = {
  notification match {
    case Email(email, title, _) =>
      s"You got an email from $email with title: $title"
    case SMS(number, message) =>
      s"You got an SMS from $number! Message: $message"
    case VoiceRecording(name, link) =>
      s"you received a Voice Recording from $name! Click the link to hear it: $link"
  }
}
val someSms = SMS("12345", "Are you there?")
val someVoiceRecording = VoiceRecording("Tom", "voicerecording.org/id/123")

println(showNotification(someSms))  // prints You got an SMS from 12345! Message: Are you there?

println(showNotification(someVoiceRecording))  // you received a Voice Recording from Tom! Click the link to hear it: voicerecording.org/id/123

 函数showNotification使用一个抽象类型Notification类型的参数,然后match Notification类型(举例来说:它找出这是否是一个Email、SMS或VoiceRecording)。在case Email(email, title, _),字段email和title在返回值时会使用,body被用_忽略了。

模式保护(Pattern guards)

pattern guard是简单的布尔表达式,用来让case更精确。只要在pattern后面加上if <boolean expression>

def showImportantNotification(notification: Notification, importantPeopleInfo: Seq[String]): String = {
  notification match {
    case Email(email, _, _) if importantPeopleInfo.contains(email) =>
      "You got an email from special someone!"
    case SMS(number, _) if importantPeopleInfo.contains(number) =>
      "You got an SMS from special someone!"
    case other =>
      showNotification(other) // nothing special, delegate to our original showNotification function
  }
}

val importantPeopleInfo = Seq("867-5309", "jenny@gmail.com")

val someSms = SMS("867-5309", "Are you there?")
val someVoiceRecording = VoiceRecording("Tom", "voicerecording.org/id/123")
val importantEmail = Email("jenny@gmail.com", "Drinks tonight?", "I'm free after 5!")
val importantSms = SMS("867-5309", "I'm here! Where are you?")

println(showImportantNotification(someSms, importantPeopleInfo))
println(showImportantNotification(someVoiceRecording, importantPeopleInfo))
println(showImportantNotification(importantEmail, importantPeopleInfo))
println(showImportantNotification(importantSms, importantPeopleInfo))

在case Email(email, _, _) if importantPeopleInfo.contains(email)中,只有当email在重要人士列表中时才会匹配。

只匹配类型(matching on type only)

你也可以像这样匹配一个类型:

abstract class Device
case class Phone(model: String) extends Device{
  def screenOff = "Turning screen off"
}
case class Computer(model: String) extends Device {
  def screenSaverOn = "Turning screen saver on..."
}

def goIdle(device: Device) = device match {
  case p: Phone => p.screenOff
  case c: Computer => c.screenSaverOn
}

 def goIdle根据Device类型的不同有不同的行为。这个在case需要在pattern上调用方法时很有用。这是一个约定:使用type的第一个字符作为case的标识符(这个case中的p和c)。

密封类(sealed classes)

trait和class可以被标记为sealed,这意味着所有的子类必须声明在同一个文件中。这个保证所有子类都是可知的:

sealed abstract class Furniture
case class Couch() extends Furniture
case class Chair() extends Furniture

def findPlaceToSit(piece: Furniture): String = piece match {
  case a: Couch => "Lie on the couch"
  case b: Chair => "Sit on the chair"
}

 这在pattern matching中很有有用,因为我们不需要catch all这个case。

 

注意

scala的pattern matching语句在通过case class来匹配代数类型时最有用。Scala也允许独立于case class的pattern定义,使用extractor objects的unapply方法(这里不太理解,需要看extractor object)。

 

分享到:
评论

相关推荐

    scala-2.10.2

    scala.util.matching - Pattern matching in text using regular expressions. scala.util.parsing.combinator - Composable combinators for parsing. scala.xml - XML parsing, manipulation, and serialization.

    scala for the impatient

    Working with higher-order functions and the powerful Scala collections library * Leveraging Scala's powerful pattern matching and case classes * Creating concurrent programs with Scala actors * ...

    Scala.Functional.Programming.Patterns.178398

    You will also explore how to currying favors to your code and how to simplify it by de-construction via pattern matching. We also show you how to do pipeline transformations using higher order ...

    Programming Scala

    * Know how to use mixin composition with traits, pattern matching, concurrency with Actors, and other essential features, * Take advantage of Scala's built-in support for XML, * Learn how to develop ...

    Scala Functional Programming Patterns(PACKT,2015)

    You will also explore how to currying favors to your code and how to simplify it by de-construction via pattern matching. We also show you how to do pipeline transformations using higher order ...

    Scala Succinctly

    Description Learning a new programming language can be a daunting task, but Scala Succinctly makes it a simple matter. Author Chris Rose guides readers through the ...Pattern Matching Closures Conclusion

    Scala for the Impatient 2nd (完整英文第二版 带书签)

    14 PATTERN MATCHING AND CASE CLASSES A2 197 14.1 A Better Switch 198 14.2 Guards 199 14.3 Variables in Patterns 199 14.4 Type Patterns 200 14.5 Matching Arrays, Lists, and Tuples 201 14.6 Extractors ...

    scala-in-action_ZH_CN:《Scala in Action》中文翻译

    ###《Scala in Action》中文翻译——个人自娱,与版权无关 目 录 第一部分: 第1章: 1.1 1.1.1 1.1.2 1.1.3 1.1.4 1.1.5 1.2 ...2.1 Scala解释器下的REPL 2.2 Scala基础 ...2.6 Pattern matching 2.7

    awesome-pattern-matching:以简单但功能强大且可扩展的方式进行Python 3.7+的模式匹配

    适用于Python的出色模式匹配( apm )pip install awesome-pattern-matching 简单的强大的可扩展的可组合功能性Python 3.7 +,PyPy3.7 + 键入(IDE友好) 提供不同的样式(表达式,声明式,语句等) 有大量适用于...

    4.样式类和模式匹配1

    1. 样例类 case class 和模式匹配 pattern matching 是一组孪生语法,它们为我们编写规则的、 1. 样例类是 Scala 用于对象模

    主题:与Java 8类似的Scala模式匹配

    Java 8的模式匹配库Motif在Java 8中提供了类似于Scala的模式匹配。 例子 嘶嘶声 IntStream . range( 0 , 101 ) . forEach( n - &gt; System . out . println( match( Tuple2 . of(n % 3 , n % 5 )) .when(tuple2(eq...

    Scala 正则表达式

    Scala 通过 scala.util.matching 包中的 Regex 类来支持正则表达式。以下实例演示了使用正则表达式查找单词 Scala : import scala.util.matching.Regex object Test { def main(args: Array[String]) { val ...

    option.cr:ƛScala的Option Monad的Crystal实现

    option.cr:ƛScala的Option Monad的Crystal实现

    fear:一些Scala单子的Ruby端口

    它受到scala实施的极大启发。 安装 将此行添加到您的应用程序的Gemfile中: gem 'fear' 然后执行: $ bundle 或将其自己安装为: $ gem install fear 用法 选项( ) 表示可选(可为空)的值。 Option的实例...

    ScalaByExample

    7.2 PatternMatching . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 47 8 Generic Types andMethods 51 8.1 Type Parameter Bounds . . . . . . . . . . . . . . . . . . . . . . . . . . . . ...

    ScalaByExample.pdf

    7.2 Pattern Matching . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 47 8 Generic Types and Methods 51 8.1 Type Parameter Bounds . . . . . . . . . . . . . . . . . . . . . . . . . . . ....

    empress:他妈的简单的演示

    将幻灯片放在目录中,并按如下所示命名,以指示演示顺序:1-getting_started.md2-practical.md3-exploratory.md4-big_projects.md5-class.md6-value_object.md7-object.md8-immutability.md9-pattern_matching.md ...

    cpp-算法精粹

    目前支持 Java, C++, C#, Python, Ruby, JavaScript, Swift, Scala, Clojure, 将来还会支持更多编程语言。 在线阅读 https://www.gitbook.com/book/soulmachine/algorithm-essentials/ 内容目录 介绍 线性表 ...

Global site tag (gtag.js) - Google Analytics