2013-04-19 14 views
32

ich zu verstehen versuchen, wie Klapp- und foldLeft und die jeweiligen reduzieren und reduceLeft Arbeit. Ich benutzte Falte und foldLeft wie mein BeispielScala: fold vs foldLeft

scala> val r = List((ArrayBuffer(1, 2, 3, 4),10)) 
scala> r.foldLeft(ArrayBuffer(1,2,4,5))((x,y) => x -- y._1) 

scala> res28: scala.collection.mutable.ArrayBuffer[Int] = ArrayBuffer(5) 

scala> r.fold(ArrayBuffer(1,2,4,5))((x,y) => x -- y._1) 
<console>:11: error: value _1 is not a member of Serializable with Equals 
       r.fold(ArrayBuffer(1,2,4,5))((x,y) => x -- y._1) 

Warum fold nicht als foldLeft funktionierte? Was ist Serializable with Equals? Ich verstehe Falte und foldLeft hat leichte unterschiedliche API-Signatur in Bezug auf generische Parametertypen. Bitte beraten. Vielen Dank.

+3

Mögliches Duplikat [Differenz zwischen Klapp- und foldLeft oder foldRight?] (Http://stackoverflow.com/q/6253978) –

+0

Welche Version von scala? –

+0

Meine scala Version 2.10.1 – thlim

Antwort

54

Die Methode fold (ursprünglich für die parallele Berechnung hinzugefügt) ist weniger leistungsfähig als foldLeft in Bezug auf Typen, auf die es angewendet werden kann. Seine Unterschrift ist:

def fold[A1 >: A](z: A1)(op: (A1, A1) => A1): A1 

Dies bedeutet, dass die Art, auf die die Faltung durchgeführt wird, hat ein übergeordneter Typ des Sammelelementtyp sein.

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

Der Grund dafür ist, dass fold können parallel durchgeführt werden, während foldLeft nicht. Dies ist nicht nur wegen des *Left Teils, was bedeutet, dass foldLeft sequentiell von links nach rechts geht, sondern auch weil der Operator op keine parallel berechneten Ergebnisse kombinieren kann - er definiert nur, wie der Aggregationstyp B mit dem Elementtyp A kombiniert wird. aber nicht wie man zwei Aggregationen vom Typ B kombiniert. Die fold Methode, die wiederum diese nicht definiert, weil die Art Aggregation A1 ein übergeordneter Typ des Elementtypen sein muss A, dass A1 >: A ist. Diese Supertypbeziehung ermöglicht es, die Aggregation und Elemente gleichzeitig zu falten und Aggregationen zu kombinieren - beide mit einem einzigen Operator.

Diese Überbegriffsbeziehung zwischen Aggregation und Elementtyp bedeutet jedoch auch, dass der Aggregationstyp A1 in Ihrem Beispiel der Supertyp (ArrayBuffer[Int], Int) sein sollte. Da das Nullelement des Aggregations ArrayBuffer(1, 2, 4, 5) von der Art ist ArrayBuffer[Int] wird der Aggregationstyp zu sein, der Supertyp von beide von diesem abgeleitet - und das ist Serializable with Equals, die nur kleinste obere eines Tupels gebunden und ein Array-Puffer.

Im Allgemeinen, wenn Sie paralleles Falten für beliebige Typen zulassen möchten (was außerhalb der Reihenfolge geschieht), müssen Sie die Methode aggregate verwenden, die definiert, wie zwei Aggregationen kombiniert werden. In Ihrem Fall:

r.aggregate(ArrayBuffer(1, 2, 4, 5))({ (x, y) => x -- y._1 }, (x, y) => x intersect y) 

Btw, versuchen Sie Ihr Beispiel mit reduce/reduceLeft Schreiben - wegen der übergeordneten Typ Beziehung zwischen dem Elementtyp und dem Aggregationstyp, der diese beiden Methoden haben, werden Sie feststellen, dass es zu einem führt ähnlicher Fehler wie der, den Sie beschrieben haben.