scala - foldleft spark
Scala: fold vs foldLeft (1)
Estoy tratando de entender cómo doblar y doblar hacia la izquierda y el respectivo reducir y reducir el trabajo izquierdo. Usé fold y foldLeft como mi ejemplo
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)
¿Por qué fold
no funcionó como foldLeft
? ¿Qué es Serializable with Equals
? Entiendo fold y foldLeft tiene una ligera firma de API diferente en términos de tipos genéricos de parámetros. Por favor avise. Gracias.
El fold
método (originalmente agregado para el cálculo en paralelo) es menos poderoso que foldLeft
en términos de tipos a los que se puede aplicar. Su firma es:
def fold[A1 >: A](z: A1)(op: (A1, A1) => A1): A1
Esto significa que el tipo sobre el que se realiza el plegado debe ser un supertipo del tipo de elemento de colección.
def foldLeft[B](z: B)(op: (B, A) => B): B
La razón es que fold
puede implementarse en paralelo, mientras que foldLeft
no puede. Esto no solo se debe a la *Left
parte *Left
que implica que foldLeft
va de izquierda a derecha secuencialmente, sino también porque el operador op
no puede combinar resultados calculados en paralelo; solo define cómo combinar la agregación tipo B
con el elemento tipo A
, pero no cómo combinar dos agregaciones de tipo B
El método de fold
, a su vez, define esto, porque el tipo de agregación A1
tiene que ser un supertipo del elemento tipo A
, que es A1 >: A
Esta relación de supertipo permite al mismo tiempo doblar la agregación y los elementos, y combinar agregaciones, ambas con un solo operador.
Pero esta relación de supertipo entre la agregación y el tipo de elemento también significa que el tipo de agregación A1
en su ejemplo debe ser el supertipo de (ArrayBuffer[Int], Int)
. Dado que el elemento cero de su agregación es ArrayBuffer(1, 2, 4, 5)
del tipo ArrayBuffer[Int]
, se deduce que el tipo de agregación es el supertipo de ambos, y que es Serializable with Equals
, el único menos límite superior de una tupla y un buffer de matriz.
En general, si desea permitir el plegado en paralelo para tipos arbitrarios (que se hace fuera de servicio), debe usar el aggregate
método aggregate
que requiere definir cómo se combinan dos agregaciones. En tu caso:
r.aggregate(ArrayBuffer(1, 2, 4, 5))({ (x, y) => x -- y._1 }, (x, y) => x intersect y)
Por cierto, intente escribir su ejemplo con reduce
/ reduceLeft
: debido a la relación de supertipo entre el tipo de elemento y el tipo de agregación que ambos métodos tienen, descubrirá que genera un error similar al que ha descrito.