scala笔记- 模式匹配

前言

大概介绍一下 scala中强大的模式匹配功能

最简单的例子

  val bools = Seq(true,false)

  bools.foreach {
    case true => println("it's ture")
    case false  => println("it's false")
  }

就是一个最简单的匹配。

类型匹配和值匹配

  for {
    x <- Seq(1,2,3.1,"one","two",true)
  } {
    val s = x match {
      case 1 => "it's one"
      case _ :Int | _:Double => s"it's a number $x"
      case "one" => "it's one"
      case _:String => s"other string $x"
      case _ => s"unexpected value $x"
    }
    println(s)
  }

基本能说明问题了

seq匹配

 val nonEmptySeq = Seq (1,2,5,6,8)

  val emptySeq = Seq.empty[Int]
  
  def seqToString[T](seq:Seq[T]):String = {
    seq match {
      case Nil => "Nil"
      case head +: tail => s"$head +: ${seqToString(tail)}"
    }
  }

  println(seqToString(nonEmptySeq))
  println(seqToString(emptySeq))

 其中的 +: 很有趣。 其实我们可以通过 1 :+ 2 :+3 :+ Nil 来构建一个 (1,2,3,Nil) 的序列。scala为了保证逆操作也可以通过 +: 来实现,所以特意写了一个单例

object +: {
  def unapply[T,Coll <: SeqLike[T, Coll]](
      t: Coll with SeqLike[T, Coll]): Option[(T, Coll)] =
    if(t.isEmpty) None
    else Some(t.head -> t.tail)
}

 对于 unapply 后续再说,从上面的代码可以看出 :+ 其实就是一个单例。 在case 中做提取的时候,其实调用的是 

case +:(head,tail) => s"$head +: ${seqToString(tail)}"

scala 通过中缀表达式,那么 就可以使用

case head +: tail => s"$head +: ${seqToString(tail)}"

 顿时有一种大道至简的感觉。

case class 匹配

case class Address(street:String,city:String,coutry:String)

  case class Person(name:String,age:Int,address: Address)

  val alice = Person("alice",21,Address("1 street","beijing","china"))
  val bill = Person("bill",29,Address("2 street","hangzhou","china"))

  Seq(alice,bill).foreach{
    case Person("alice",_ ,Address(_,city,_)) => println(s"hello alice .you are from $city")
    case Person("bill",_,_) => println("hello bill")
    case _ => println("who are you")
  }

直接看代码。 case class的匹配在 akka中用户非常大,可以让代码非常优雅。可以说就算从来没碰过scala人都知道这个匹配的意思。

unapply

  class Person( val name:String,val age:Int)

  object Person {
    def apply(name: String, age: Int): Person = new Person(name, age)

    def unapply(person: Person): Option[(String, Int)] = Some((person.name,person.age))
  }

  val person = Person("bill",29)

  person match {
    case Person(_,29) => println("you are 29")
    case _ => "who are you"
  }

 对于scala来说,希望能支持构造(apply)和解构(unapply)的标准语法。之前提到的case class,其实大体的作用就是如上面所说,自动帮我们写了一个unapply的方法。对于的入参就是对象本身,出参是一个Option(scala2.11.1以后放松了限制,只需要返回的对象实现了isEmpty 和 get方法就ok). 其中apply 和 unapply互为逆操作。

正则表达式的匹配

val  TtidRE = "(\\d+)@(.+)_(.+)_(\\d|.+)".r

    val ttid = "201200@taobao_iphone_2.1.0"

  ttid match {
    case TtidRE(channel,client,platform,version) =>
      println(s"channel=$channel,client=$client,platform=$platform,version=$version")
    case _ => println("not match")
  }

如此优雅的代码!

猜你喜欢

转载自chenjingbo.iteye.com/blog/2335664