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) } }
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