Scala 专题教程-Extractors(3):无参数和带一个参数的模式定义

jerry Scala 2015年11月25日 收藏

前面例子中的unapply方法在匹配成功时返回一个二元组。这可以很容易的推广到多于两个变量的情况。为了绑定N个变量,unapply方法可以返回一个N元祖,封装在Some中。
对于一个只绑定一个变量的情况有些特殊。Scala没有所谓“一元组”,为返回一个变量,该变量直接封装在Some中返回。下面的例子的Twice匹配一个含有两个连续的相同字符串的情况。

object Twice {
	def apply(s:String) = s + s
	def unapply(s:String):Option[String] ={
		val length=s.length/2
		val half = s.substring(0,length)
		if(half == s.substring(length)) Some(half) else None
	}
}

一个Extractor也可以绑定任何变量,这种情况下可以返回true和false代表匹配成功与否。比如下面的例子匹配一个字符串是否都是大写字母:‘

object UpperCase {
	def unapply(s:String):Boolean = s.toUpperCase ==s 
}

这个例子只定义了unapply方法,因为这里定义apply方法无任何意义。
之后我们可以利用上面定义的Twice 和 UpperCase Extractor 组合构造组合的模式定义(还记得之前提到的Monoid,设计模式Option类型就是一个Monoid,Monoid一个特点就是可以任意组合)

def userTwiceUpper(s:String) = s match{
	case EMail(Twice(x @ UpperCase()),domain) =>
		"match:" + x + " in domain " + domain
	case _ => "no match"
}

第一个模式定义去匹配所有的Email地址,这个Email地址的用户名为大写,并且有两个相同的字符串构成。例如:

scala> userTwiceUpper("DIDI@hotmail.com")
res1: String = match:DI in domain hotmail.com

scala> userTwiceUpper("DIDO@hotmail.com")
res2: String = no match

scala> userTwiceUpper("didi@hotmail.com")
res3: String = no match

在这个模式定义中,UpperCase后面跟了一个空括号,这个空括号是必须的,否则模式变成匹配和UpperCase相等。即使UpperCase没有绑定任何变量,但你可以利用前面Scala 专题教程-Case Class和模式匹配(5): 模式的种类(四)的方法为这个模式定义绑定一个自定义的变量。这是使用“@”来定义的。为x。