k47.cz    — každý den dokud se vám to nezačne líbit
foto Praha výběr povídky kultura | twitter FB


Scala - pattern matching

7. 6. 2011 — k47

Seznam všechn způsobů, jak lze provádět pattern matching.


a match {
  case a =>              // shoda pro jakoukoli hodnotu
  case _ =>              // to samé, ale bez pojmenované proměnné
  case a: Something =>   // case a if a.isInstanceOf[Something] && a != null  // pro null nikdy nenastane shoda
  case Something =>      // case a if a == Something, toto pravidlo je použito v případě `case None' nebo `case Nil'
  case Something() =>    // case a: Something
  case A(b) =>
  case `variable` =>     // case v if v == variable
  case A(`b`) =>         // case A(x) if x == b
  case A(B) =>           // case A(b) if b == B  // pokud název proměnné začíná velkým písmenem nebo je v zpětných apostrofech, bere se jako konstanta
  case A("string literal") => // lze použít jakýkoli literál (Int, String, Boolean, Char, Symbol)
  case A(a, B(C(c), b)) => // vzory lze libovolně vnořovat
  case A(_, a) =>        // pojmenovat můžeme jenom některé proměnné
  case A() | B() =>      // odpovídá jednomu ze dvou vzorů
  case A(_) | B(_, _) => // není možné pojmenovat parametry
  case b @ B(x, y) =>    // objekt B je zachycen do proměnné `b' a zároveň jsou zachyceny jeho dílčí části v `x' a `y'
  case B(a @ A(_), _) => // @ konstrukci lze pochopitelně libovolně zanořovat
  case a: Array[Int] =>  // můžeme se dotazovat na typový parametr polí
  case a: List[_] =>     // ale ne na typ. param. ostatních generických typů (jinak nás uvítá unchecked warning)

  // sekvence
  case List(0, 1, 2) =>  // seznam, který má délku 3 a obsahuje položky: 1, 2, 3
  case List(1, _, _) =>  // seznam, který má délku 3 a začíná integerem 1
  case List(1, _*) =>    // seznam délky > 1, který začíná integerem 1

  case (a, b, c) =>      // case Tuple3(a, b, c)
  case 1 :: Nil =>       // infixový vzor, obdoba `case List(1)' nebo přesněji `case ::(1, Nil)'
  case 1 :: 2 :: _ =>    // obdoba `case ::(1, ::(2, _)' nebo `case List(1, 2, _*)'
}

A nejlepší je, že soukolí pattern matchingu můžete používat i v definici proměnných. Téměř všechno, co může následovat case, může másledovat val.

val myTuple = (123, "xxx")
val (a, b) = myTuple
val List(1, _, 3) = myList

dokonce můžete použít i takovéhle zrůdnosti:

val a @ Some(b) = Some(1) // a = Some(1); b = 1

Maličkým problémem může být, že pokud nenastane shoda, uvítá vás přátelská MatchError.

Ještě jedna drobnost: pokud definujete třídu s několika skupinami argumentů, pattern matching lze provádět jen na první z nich.

case class A(a: Int)(b: String)

A(1)("something") match {
  case A(_)(_) => // není možné
  case A(_) =>    // tohle je už lepší
}

vstoupit do diskuze    sdílet na facebooku, twitteru, google+
publikováno 7. 6. 2011

příbuzné články:
Ceylon Project
Go třídy ve Scale 📷
Scala - Pattern matching a regulární výrazy 📷
Scala - články 📷
Scala - trait Dynamic 📷
Kompozice monád & Option 📷

píše k47 & hosté, ascii@k47.cz