REMARQUE: je suis sur Scala 2.8 - cela peut-il être un problème?
Pourquoi ne puis-je pas utiliser la fonction fold
de la même manière que foldLeft
ou foldRight
?
Dans le Set scaladoc il dit que:
Le résultat du pliage ne peut être qu'un super-type du paramètre de type de cette collection parallèle
T
.
Mais je ne vois aucun paramètre de type T
dans la signature de la fonction:
def fold [A1 >: A] (z: A1)(op: (A1, A1) ⇒ A1): A1
Quelle est la différence entre le foldLeft-Right
et fold
, et comment utiliser ce dernier?
EDIT: Par exemple, comment pourrais-je écrire un pli pour ajouter tous les éléments dans une liste? Avec foldLeft
ce serait:
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)(_ + _)
^
Vous avez raison sur l'ancienne version de Scala étant un problème. Si vous regardez la page scaladoc pour Scala 2.8. 1, vous ne verrez aucun pli défini ici (ce qui est cohérent avec votre message d'erreur). Apparemment, fold
a été introduit dans Scala 2.9.
Réponse courte:
foldRight
s'associe à droite. C'est à dire. les éléments seront accumulés de droite à gauche:
List(a,b,c).foldRight(z)(f) = f(a, f(b, f(c, z)))
foldLeft
s'associe à gauche. C'est à dire. un accumulateur sera initialisé et des éléments seront ajoutés à l'accumulateur de gauche à droite:
List(a,b,c).foldLeft(z)(f) = f(f(f(z, a), b), c)
fold
est associatif en ce que l'ordre dans lequel les éléments sont additionnés n'est pas défini. C'est à dire. les arguments de fold
forment un monoïde.
fold
, contrairement à foldRight
et foldLeft
, n'offre aucune garantie quant à l'ordre dans lequel les éléments de la collection seront traités. Vous voudrez probablement utiliser fold
, avec sa signature plus contrainte, avec des collections parallèles, où le manque d'ordre de traitement garanti aide la collection parallèle à implémenter le pliage de manière parallèle. La raison du changement de signature est similaire: avec les contraintes supplémentaires, il est plus facile de faire un pli parallèle.
D'accord avec d'autres réponses. pensé à donner un exemple illustratif simple:
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
Pour votre exemple particulier, vous le coderiez de la même manière que vous le feriez avec foldLeft.
val ns = List(1, 2, 3, 4)
val s0 = ns.foldLeft (0) (_+_) //10
val s1 = ns.fold (0) (_+_) //10
assert(s0 == s1)