1 Pattern Matching 2 Patternguards 3 Sealed Klassen 4 Option Type

Werbung
Scala - Pattern Matching
1 Pattern Matching
Pattern Matching wird genutzt, um Daten anhand ihrer Struktur zu verarbeiten.
1.1 Konstante Pattern
• Jede Konstante kann für match benutzt werden.
• Beim Verwenden einer vorher definierten val, muss der erste
Buchstabe groß geschrieben werden.
• Als Alternative kann der Name der vorher definierten Konstanten in Backticks gesetzt werden.
val Pi = Math.Pi
val e = Math.E
expr match {
case 1 => println("eins")
case Pi => println(Pi)
case ‘e‘ => println(e)
case _ => println("etwas anders")
}
18. Mai 2010
1.6 Type patterns
• Bestimmen des Variablentyps.
• Erlaubt das gleichzeitige Feststellen des Typs und das Casten einer Variable.
def cast(x: Any) = x match {
case i: Int => println("Integer: " + i)
case s: String => println("String: " + s)
case d: Double => println("Double: " + d)
case other => println("Etwas anderes: " + other)
}
1.7 Variablen binden
• Weiterverwenden eines inneren Patterns durch das @Zeichen.
case class OneString(a: String)
case class TwoStrings(a: OneString, b: OneString)
def expr(x: Any) = x match {
case TwoStrings(OneString(a), e @ OneString(b)) => e
case _ =>
}
1.2 Variable Pattern
• Beginnt der Parameter eines case mit Kleinbuchstaben, wird
dieser als variables Pattern interpretiert.
• Ein variables Pattern wird dem übergebenen Wert zugewiesen
(ähnlich wie das Wildcard _, aber das übergebene Objekt
wird daran gebunden).
def patternMatch(x: Any) = x match {
case a => println(a)
}
1.3 Konstruktor Pattern
• Jede Klasse mit dem Schlüsselwort case kann als case-Klasse
verwendet werden.
• Der match findet auf den Konstruktor der Klasse statt.
case class Person(name: String, age: Int)
person match {
case Person("Alice", 25) => println("Hi Alice!")
case Person(name, age) => println(name + " : " + age)
}
2 Patternguards
• Ein Patternguard erlaubt es, über eine if-Bedingung zu
prüfen, ob eine bestimmte Eigenschaft erfüllt ist.
• Ein match findet nur statt, wenn der Patternguard true
zurückgibt.
person match {
case i: Int if i > 0 => println("Wert ist größer 0")
case i: Int => println("Wert ist kleiner oder gleich 0")
}
3 Sealed Klassen
• Alle case-Klassen werden in einer Datei erzeugt und sind von
einer Abstrakten Basisklasse mit dem Schlüsselwort sealed
abgeleitet, die sich auch in der selben Datei befindet.
• Mit dem Schlüsselwort sealed wir sichergestellt, dass keine
zusätzlichen case-Klassen erzeugt werden.
sealed class BinaryTree
case class Node(value: Int, l: BinaryTree, r: BinaryTree)
extends BinaryTree
case object Empty extends BinaryTree
4 Option Type
1.4 Pattern Sequenzen
• Suche nach bestimmten Sequenzen.
• Mit dem Pattern _* kann auf eine Sequenz von Elementen
angesprochen werden.
expr match {
// 1. Element ist eine 0, genau 3 Elemente
case List(0, _, _) => println("first")
// 2. Element ist eine 4, 2 oder mehr Elemente
case List(_, 4, _*) => println("second")
// Beliebig viele Elemente oder leere Liste
case List(_*) => println("third")
}
• null zurückliefern ist in Scala nicht immer möglich.
• Als Alternative gibt es den Option Type, der entweder
Some(x) oder None zurückliefert.
• Zum Extrahieren des Wertes aus Some() bieten sich ein pattern match an.
scala> def show(x: Option[String]) = x match {
case Some(s) => s
case None => "?"
}
5 Pattern außerhalb von match
Pattern sind in vielen Teilen von Scala erlaubt und nicht nur
in match-Ausdrücken.
1.5 Tuple patterns
• Auch Tuple können mit Hilfe eines Pattern Macht gefunden
werden.
def tuple(x: Any) = x match {
case (a, b, c) => "Dreier Tupel: " + a + ", " + b + ", " + c
case _ =>
}
Dennis Wilfert
5.1 Pattern in Variablendefinitionen
• Tuple lassen sich einfach in einzelne Variablen aufteilen.
scala> val tuple = (123, "abc")
tuple: (Int, java.lang.String) = (123,abc)
scala> val (n, s) = tuple
n: Int = 123
s: java.lang.String = abc
1
Scala - Pattern Matching
5.2 case-Sequenzen als partielle Funktionen
• Eine Sequenz von case kann in jeder partiellen Funktion als
Eintrittspunkt verwendet werden.
• Eine case-Sequenz hat mehrere Eintrittspunkte, jede mit ihrer eigenen Liste von Parametern.
18. Mai 2010
7 Reguläre Ausdrücke (regular expressions)
• Scala übernimmt die regular expression syntax aus Java.
• Nach einem import scala.util.matching.Regex können reguläre Ausdrücke verwendet werden.
val Words = new Regex("(\\w+)")
val withDefault: Option[Int] => Int = {
case Some(x) => x
case None => 0
}
• Zurückgeben eines bestimmten Objekts aus einer Liste.
• PartialFunktion liefert Methoden um sicherzustellen, dass
die Liste wirklich so viele Elemente besitzt. Ansonsten
würde eine Compilerwarnung auftreten.
• regex findFirstIn str findet erstes Auftreten des regulären
Ausdrucks.
• regex findAllIn str findet jedes Auftreten des regulären
Ausdrucks.
• regex findPrefixOf str. Der reguläre Ausdruck muss an erster Position auftreten.
val input = "Einzelne Wörter eines Strings"
val second: PartialFunction[List[Int],Int] = {
case x :: y :: _ => y
}
for (s <- Words findAllIn input)
println(s)
second.isDefinedAt(List())
7.1 Extrahieren mit regulären Ausdrücken
• Jeder reguläre Ausdruck in Scala definiert einen Extractor.
5.3 Pattern in for-Ausdrücken
• Verwenden von Pattern in for-Ausdrücken.
val tupleList = List( ("Dennis", "Wilfert"), ("John", "Doe") )
for((a, b) <- tupleList)
println("Vorname: " + a + " Nachname: " + b)
Vorname: Dennis Nachname: Wilfert
Vorname: John Nachname: Doe
// Sucht alle Zahlen (negativ und positiv) in einem String
val Decimal = """(-)?(\d+)(\.\d*)?""".r
scala> val Decimal(sign, integerpart, decimalpart) = "-1.23"
sign: String = integerpart: String = 1
decimalpart: String = .23
6 Extractoren
6.1 Extractoren
• Extractoren erlauben es, ein Pattern zu erstellen ohne eine
damit verbundene case-Klasse zu schreiben.
• Ein Extractor ist ein object, dass eine Methode unapply besitzt.
• Wird das Extractorobjekt für ein Patternmatch verwendet
wird bei einem Match die Methode unapply aufgerufen.
• Eine Methode apply ist oft auch vorhanden, aber nicht zwingend notwendig..
• Sind in einem Objekt apply und unapply definiert, sollte ein
Aufruf unapply(apply(a, b)) Some(a, b) zurückliefern.
object Twice {
def apply(x: Int): Int = x * 2
def unapply(z: Int): Option[Int] = if (z%2 == 0) Some(z/2)
else None
}
twice match {
case Twice(n) => println(n)
}
6.2 Extractoren mit variabler Argumentzahl
• Für einen Extractor mit einer variablen Anzahl an Rückgabewerten, muss eine Methode unapplySeq implementiert
werden.
• Das Ergebnis von unapplySeq muss Option[Seq[T]] sein.
def unapplySeq(s: String): Option[Seq[String]] =
Some(s.split(" "))
}
Dennis Wilfert
2
Herunterladen