2016-09-23 4 views
0

Ich schrieb einige Ereignisse in FSM und entdeckte etwas, das ich nicht erklären kann, wenn Muster zusammenpassen. Ich dachte, das Folgende sei völlig legal, das heißt, ich kann diesem Akteur entweder eine Nachricht senden, die ein Vektor [A] oder ein Vektor [B] ist.Wie erklärt man diese Mustervergleichsbeispiele?

when(State) { 
    case Event(content: Vector[A], _) => { 
     println("matched A") 
     stay 
    } 
    case Event(content: Vector[B], _) => { 
    println("matched B") 
    stay 
    } 
} 

jedoch , wenn ich die Schauspieler einen Vektor [B] Nachricht senden führt es zu

java.lang.ClassCastException: B cannot be cast to A 

Also im Grunde versucht, die erste Veranstaltung anzupassen eventhough das nächste Spiel würde.

Ich habe versucht, eine noch einfachere Muster Übereinstimmung Beispiel zu machen;

object Pattern extends App { 
    val n = Vector(1,2,3) 
    val s = Vector("S", "S", "S") 
    n match{ 
     case e:Vector[String] => println("matched string") 
     case v:Vector[Int] => println("matched int") 
    } 

}

Dies ist eigentlich nicht legal;

Error:(8, 12) pattern type is incompatible with expected type; 
found : Vector[String] 
required: scala.collection.immutable.Vector[Int] 
case e:Vector[String] => println("matched string") 

Allerdings darf ich meinen Code ausführen, wenn ich die folgende Besetzung mache;

object Pattern extends App { 
    val n = Vector(1,2,3).asInstanceOf[Vector[Any]] 
    val s = Vector("S", "S", "S") 
    n match{ 
    case e:Vector[String] => println(n(0).getClass) 
    case v:Vector[Int] => println("matched int") 
    } 
} 

Das, was ich dann seltsam finde ist, dass ich offenbar sagen, dass jeder einen String passen könnte, aber der Druck ist java.lang.Integer. Also sollte ich darüber nachdenken, da ich einen Vektor [Int] habe, den ich sage, ist ein Vektor [Beliebige], da Vektor [Beliebige] ein Vektor [Zeichenkette] sein kann, stimmt es mit diesem Muster überein und wieder, da es wirklich ein Vektor ist [ Int] Ich maskiere als Vector [Beliebige] der Druck ist auch in Ordnung.

Kann jemand diese mustervergleichenden Beobachtungen erklären?

und wie sollte ich die Nachrichten einrichten, damit mein Status beide Nachrichten von Vector [A] und Vector [B] verarbeiten kann?

+1

Was sind 'A' und 'B'? Kannst du ein [MCVE] posten? –

+0

A und B sind Fallklassen. Ein vollständiges und überprüfbares Beispiel (in dem Sinne, dass Sie es ausführen könnten, würde viel mehr "unnötigen" Code für den Akka FSM benötigen. Der andere Code würde laufen (kopieren und vorbei). – stian

+0

Die Frage ist nicht wirklich über FSM, es ist über Mustervergleich und Typen.Man könnte das Problem isolieren und leicht reproduzierbar erstellen. –

Antwort

1

Durch Typlöschung des jvm-Typs gehen Informationen zur Laufzeit verloren Diese Art der Mustererkennung (Mustererkennung mit höherwertigen Typen) wird nicht direkt unterstützt.

Hier sind die Möglichkeiten, um dieses Problem

Stattdessen empfehle ich Ihnen wickeln Sie den Vektor in einen anderen Behälter zu erhalten.

sealed trait Vectors 

case class VectorString(vs: Vector[String]) extends Vectors 

case class VectorInt(vi: Vector[Int]) extends Vectors 

def doStuff(v: Vectors) = v match { 
case VectorString(vs) => //be sure that vs is Vector[String] 
case VectorInt(vi) => 
} 

Wege zur Mustererkennung generische Typen in Scala

Mit TypeTag

import scala.reflect.runtime.universe._ 

def handle[A: TypeTag](a: A): Unit = 
    typeOf[A] match { 
    case t if t =:= typeOf[List[String]] => 
     // list is a string list 
     val r = a.asInstanceOf[List[String]].map(_.length).sum 
     println("strings: " + r) 

    case t if t =:= typeOf[List[Int]] => 
     // list is an int list 
     val r = a.asInstanceOf[List[Int]].sum 
     println("ints: " + r) 

    case _ => // ignore rest 
    } 

val ints: List[Int] = Nil 

handle(List("hello", "world")) // output: "strings: 10" 
handle(List(1, 2, 3))   // output: "ints: 6" 
handle(ints)     // output: "ints: 0" it works! 
+0

danke pamu. Ich werde jetzt nachsehen. – stian