2013-09-03 21 views
7

Gibt es einen Scala-Trick, um Mustervergleiche mit Map-Schlüsseln zu ermöglichen? Mit anderen Worten, ich möchte einen Extraktor haben, der neben der Map-Instanz auch einen Schlüsselwert akzeptiert, der bedeutet, dass dieses Muster nur dann übereinstimmen soll, wenn der verknüpfbare Wert eine Instanz von Map ist und ein Eintrag mit dem angegebenen Schlüssel vorhanden ist in ihr und der Wert für diesen Eintrag unterliegen rekursive Mustererkennung.Mustervergleich gegen Scala Map-Einträge

Etwas wie folgt aus:

myMap match { 
    case MyMap("a")(a) => // do smth with value a 
    case MyMap("b")(MyMap("c")(c)) => // do smth with value c 
} 

Update:

Ich habe einen Weg gefunden, näher an das Ziel zu nähern, aber es ist noch nicht perfekt, weil es Definition von synthetischen Schlüssel-Wert impliziert -halter:

case class MapKey[K](key: K) { 
    def unapply(o: Any) = o match { 
    case m: Map[K, _] ⇒ m.get(key) 
    case _ ⇒ None 
    } 
} 

val m1 = Map("a" → "aa", "b" → Map("c" → "cc")) 
val m2 = Map("a" → "aa", "d" → "dd") 

val b = MapKey("b") 
val c = MapKey("c") 
val d = MapKey("d") 

for (m ← List(m1, m2)) m match { 
    case b(c(x)) ⇒ println(s"b > c: $x") 
    case d(x) ⇒ println(s"d: $x") 
} 

ähnliche Frage: Can extractors be customized with parameters in the body of a case statement (or anywhere else that an extractor would be used)?

Feature-Anfrage: SI-5435

+1

Sind Sie sicher, dass Sie auch passen, ob 'myMap' ist eine Karte? Was könnte es sonst sein? – ziggystar

+0

Worauf wartet Ihr zweiter Fall? Wie sieht myMap aus, wenn es zusammenpasst? – Shadowlands

+0

Dies ist ein vereinfachtes Beispiel. Eigentlich entwickle ich eine Scala-Bibliothek für Operationen auf Apple Cocoa-Typen, die von NSObject abgeleitet sind. Insbesondere besteht die Aufgabe darin, die sehr komplizierte iOS-Plist-Datei mit mehreren alternativen Methoden zu analysieren, um dasselbe zu beschreiben. –

Antwort

1

Vielleicht suchen Sie eine Lösung, die Sie nicht wirklich brauchen? Ich kann mir hier keine Extraktoren vorstellen. Sie können PF verwenden, wenn Sie Schlüssel-Wert-Paare passen wollen:

val map = Map[String, String]("a" -> "b") 

def matchTuple[A,B,C](map: Map[A,B])(pf: PartialFunction[(A,B), C]) = 
    map.collectFirst(pf) 

matchTuple(map) { 
    case ("a", b) => println("value for a is " + b) 
} 

Rückgabetyp ist eine Option [Unit], weil wir collectFirst verwenden und println

+0

PartialFunction ist verkettet mit und dann und optional-über. Lift ist die Art, wie ich diesen Algorithmus bisher implementiert. Ich bin jedoch neugierig, ob es möglich ist, dies auf eine präzisere Art und Weise zu tun. –

+1

Ich denke, es ist eine mathematisch falsche Aufgabe. Die Verwendung einer Übereinstimmung, um ein Element einer ungeordneten Karte zu finden, kann zu unvorhergesehenen Ergebnissen führen –