前面例子中的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。