在scala user邮件列表中看到一个函数,判断一个对象是否是元组。从这个函数中,Easwy才了解到原来模式匹配(Pattern Match)也可以应用于正则表达式,这使得在scala中使用正则表达式(regex)更加容易了。另外,这个函数还展现了scala的另外两个特点:
函数主体如下,为了方便讲解,在前面加了行号:
val Ptrn = """scala.Tuple(d+)""".r def checka( x: Class[ _ ]) : Option[ Int ] = x.getName match { case Ptrn( i ) => Some( i.toInt ) case _ => { val sc = x.getSuperclass; if( sc != null ) checka( sc ) else None } } def isTuple( x: AnyRef ) = if( x.isInstanceOf[ Product ]) checka( x.getClass ) else None
行3定义了一个递归函数checka(),它的参数是Class[_],返回值是Option[Int]类型。参数”Class[_]“的意思是这个函数可以接受任意Class[A]类型,也就是接受任何参数化的Class类型(Type Parameterization)。
Easwy感觉checka()函数中的递归写的不是很好,在看过”The Little Schemer”后,Easwy更倾向与下面的写法:
def checka(x: Class[_]): Option[Int] = x match { case null => None case _ => x.getName match { case Ptrn(i) => Some(i.toInt) case _ => checka(x.getSuperclass) } }
下面是Easwy用来测试该函数的程序,全文如下:
object TestTuple { def main(args: Array[String]) { class ttt(a: Any, b: Any, c: Any) extends Tuple3(a, b, c) val test = List(new Tuple2(1, 2), new ttt(1, 2, 3), "Hello World") for (elem <- test) isTuple(elem) match { case None => println("Not Tuple") case Some(x) => println("Is Tuple" + x) } } val Ptrn = """scala.Tuple(d+)""".r def checka(x: Class[_]): Option[Int] = x match { case null => None case _ => x.getName match { case Ptrn(i) => Some(i.toInt) case _ => checka(x.getSuperclass) } } def isTuple( x: AnyRef ) = if( x.isInstanceOf[ Product ]) checka( x.getClass ) else None}
有兴趣的朋友可以编译运行一下,体会一下scala的简捷与优雅。