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.util.matching - Pattern matching in text using regular expressions. scala.util.parsing.combinator - Composable combinators for parsing. scala.xml - XML parsing, manipulation, and serialization.
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 * ...
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 ...
* 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 ...
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 ...
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
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》中文翻译——个人自娱,与版权无关 目 录 第一部分: 第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
适用于Python的出色模式匹配( apm )pip install awesome-pattern-matching 简单的强大的可扩展的可组合功能性Python 3.7 +,PyPy3.7 + 键入(IDE友好) 提供不同的样式(表达式,声明式,语句等) 有大量适用于...
1. 样例类 case class 和模式匹配 pattern matching 是一组孪生语法,它们为我们编写规则的、 1. 样例类是 Scala 用于对象模
Java 8的模式匹配库Motif在Java 8中提供了类似于Scala的模式匹配。 例子 嘶嘶声 IntStream . range( 0 , 101 ) . forEach( n - > System . out . println( match( Tuple2 . of(n % 3 , n % 5 )) .when(tuple2(eq...
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实现
它受到scala实施的极大启发。 安装 将此行添加到您的应用程序的Gemfile中: gem 'fear' 然后执行: $ bundle 或将其自己安装为: $ gem install fear 用法 选项( ) 表示可选(可为空)的值。 Option的实例...
7.2 PatternMatching . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 47 8 Generic Types andMethods 51 8.1 Type Parameter Bounds . . . . . . . . . . . . . . . . . . . . . . . . . . . . ...
7.2 Pattern Matching . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 47 8 Generic Types and Methods 51 8.1 Type Parameter Bounds . . . . . . . . . . . . . . . . . . . . . . . . . . . ....
将幻灯片放在目录中,并按如下所示命名,以指示演示顺序:1-getting_started.md2-practical.md3-exploratory.md4-big_projects.md5-class.md6-value_object.md7-object.md8-immutability.md9-pattern_matching.md ...
目前支持 Java, C++, C#, Python, Ruby, JavaScript, Swift, Scala, Clojure, 将来还会支持更多编程语言。 在线阅读 https://www.gitbook.com/book/soulmachine/algorithm-essentials/ 内容目录 介绍 线性表 ...