Differenza tra piega e piega a sinistra o piega a destra?

NOTA: Sono su Scala 2.8-può essere un problema?

Perché non posso usare la funzione fold come foldLeft o foldRight ?

Nel set scaladoc dice che:

Il risultato del folding può essere solo un supertipo del parametro di tipo T di questa collezione parallela.

Ma non vedo alcun parametro di tipo T nella firma della funzione:

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

Qual è la differenza tra foldLeft-Right e fold , e come faccio a usare quest’ultimo?

EDIT: Ad esempio, come scriverei una piega per aggiungere tutti gli elementi in una lista? Con foldLeft sarebbe:

 val foo = List(1, 2, 3) foo.foldLeft(0)(_ + _) // now try fold: foo.fold(0)(_ + _) >:7: error: value fold is not a member of List[Int] foo.fold(0)(_ + _) ^ 

Hai ragione riguardo alla vecchia versione di Scala come un problema. Se guardi la pagina dello scaladoc per Scala 2.8.1, non vedrai alcuna piega definita lì (che è coerente con il tuo messaggio di errore). Apparentemente, fold stato introdotto in Scala 2.9.

Risposta breve:

soci di foldRight a destra. Gli elementi verranno accumulati nell’ordine da destra a sinistra:

 List(a,b,c).foldRight(z)(f) = f(a, f(b, f(c, z))) 

foldLeft associa a sinistra. Ad esempio, un accumulatore verrà inizializzato e gli elementi verranno aggiunti all’accumulatore nell’ordine da sinistra a destra:

 List(a,b,c).foldLeft(z)(f) = f(f(f(z, a), b), c) 

fold è associativo in quanto l’ordine in cui gli elementi vengono sumti insieme non è definito. Vale a dire gli argomenti da fold formano un monoide .

fold , contrariamente a foldRight e foldLeft , non offre alcuna garanzia circa l’ordine in cui verranno elaborati gli elementi della collezione. Probabilmente vorrai usare la fold , con la sua firma più vincasting, con raccolte parallele, in cui la mancanza di un ordine di elaborazione garantito aiuta la raccolta parallela a implementare la piegatura in modo parallelo. Il motivo per cambiare la firma è simile: con i vincoli aggiuntivi, è più facile creare una piega parallela.

Per il tuo esempio particolare, lo codificheresti nello stesso modo in cui faresti con foldLeft.

 val ns = List(1, 2, 3, 4) val s0 = ns.foldLeft (0) (_+_) //10 val s1 = ns.fold (0) (_+_) //10 assert(s0 == s1) 

D’accordo con altre risposte. pensato di dare un semplice esempio illustrativo:

  object MyClass { def main(args: Array[String]) { val numbers = List(5, 4, 8, 6, 2) val a = numbers.fold(0) { (z, i) => { println("fold val1 " + z +" val2 " + i) z + i } } println(a) val b = numbers.foldLeft(0) { (z, i) => println("foldleft val1 " + z +" val2 " + i) z + i } println(b) val c = numbers.foldRight(0) { (z, i) => println("fold right val1 " + z +" val2 " + i) z + i } println(c) } } 

Il risultato è auto esplicativo:

 fold val1 0 val2 5 fold val1 5 val2 4 fold val1 9 val2 8 fold val1 17 val2 6 fold val1 23 val2 2 25 foldleft val1 0 val2 5 foldleft val1 5 val2 4 foldleft val1 9 val2 8 foldleft val1 17 val2 6 foldleft val1 23 val2 2 25 fold right val1 2 val2 0 fold right val1 6 val2 2 fold right val1 8 val2 8 fold right val1 4 val2 16 fold right val1 5 val2 20 25