2017-02-08 7 views
2

Ich habe einen ConfigRule Eigenschaft, die transform hat Methode alsTypenkonflikt, wenn reduceLeft Lauf

trait ConfigRule { 
    final def transform(doc: Node): Node = { .....} 
} 

Dann habe ich ConfigTransformer haben, die wie transform Methode hat sieht aus, als

trait ConfigTransformer { 
    def transform(doc: Node, rules: Seq[ConfigRule]) = { 
    rules.reduceLeft((x, y) => x.transform(doc).andThen(y.transform(_))) 
    } 
} 

Ich versuche, dies zu laufen als

object Runner extends App { 
    override def main(args: Array[String]): Unit = { 
    val n1 = NewNodeRule(<foo/>, <bar/>, Seq.empty, "adding bar under foo") 
    val n2 = NewNodeRule(<garage/>, <car/>, Seq.empty, "adding car under garage") 

    ConfigTransformer.transform(<Root/>, Seq(n1, n2)) 
    } 
} 

Ich bekomme Kompilierungsfehler als

Error:(18, 56) type mismatch; 
found : PartialFunction[Int,scala.xml.Node] 
required: solutions.xml.ConfigRule 
    rules.reduceLeft((x, y) => x.transform(doc).andThen(y.transform(_))) 

Was mache ich falsch?

+1

'transform()' gibt einen 'Node' zurück. Was ist die Definition von 'Node'? Wie/warum soll es die 'andThen()' Methode haben? – jwvh

Antwort

4

Ich bin kein Experte Scala noch, aber das Problem ist, dass Sie nicht Objekt vom Typ ConfigRule in reduceLeft Anweisung zurückgeben können (es ist ein Node und das ist, warum Sie einen Fehler). Was Sie suchen, ist foldLeft. Hier ein Beispiel:

trait ConfigTransformer { 
    def transform(doc: Node, rules: Seq[ConfigRule]) = { 
     rules.foldLeft(doc)((d, x) => x.transform(d)) 
    } 
} 
+0

Danke, das ist, was ich gesucht habe – daydreamer

2

Nun ... die Sache ist, dass reduceLeft für ein Seq[A] hat folgende Signatur,

def reduceLeft[B >: A](op: (B, A) ⇒ B): B 

was bedeutet, dass Ihre Funktion reduziert op sollte ein accumulator: B und currentElem: A nehmen und soll zurückkehren a B, wobei B etwas super-class von A ist.

Eine wichtige Sache zu beachten über reduceLeft ist, dass die erste Reduktion ie. Die erste Berechnung des accumulator erfolgt mit den ersten und zweiten Elementen von Seq als Parameter.

Mit anderen Worten ... nur Elemente im Seq sind an reduceLeft beteiligt.

Für die Anwendungsfälle, wo man mit einem anderen Wert als Anfangsspeicher, da dies Sie solche starten mag, können Sie foldLeft verwenden sollen, die die folgende Signatur hat,

def foldLeft[B](z: B)(op: (B, A) ⇒ B): B 

Beachten Sie, dass es sich um eine nehmen Initial accumulator: B (z hier) und eine fold Funktion als Parameter. Auch ... B hier kann jede Art sein, die Sie wollen, ohne jede Beziehung zu A. Und das ist genau der Fall für Sie,

Nun, wenn Sie mit foldLeft dies tun wollte,

trait ConfigTransformer { 

    def transform(doc: Node, rules: Seq[ConfigRule]) = 
    rules.foldLeft(doc)((acc, elem) => elem.transform(acc)) 

}