Différence entre foldle et foldLeft ou foldRight?
NOTE: je suis sur Scala 2.8-peut-ê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 est dit que:
le résultat du pliage ne peut être qu'un supertype du paramètre de type de cette collection parallèle
T
.
mais je ne vois aucun paramètre de type T
dans la fonction signature:
def fold [A1 >: A] (z: A1)(op: (A1, A1) ⇒ A1): A1
Quelle est la différence entre le foldLeft-Right
et le fold
, et comment utiliser ce dernier?
EDIT: par exemple comment écrire un pli pour ajouter tous les éléments d'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)(_ + _)
^
5 réponses
vous avez raison à propos de L'ancienne version de Scala étant un problème. Si vous regardez la scaladoc page pour Scala 2.8.1, vous ne verrez aucun pli défini (ce qui est compatible avec votre message d'erreur). Apparemment, fold
a été introduit dans Scala 2.9.
courte réponse:
foldRight
associés à droite. I. e. les éléments seront accumulés dans de droite à gauche:
List(a,b,c).foldRight(z)(f) = f(a, f(b, f(c, z)))
foldLeft
associés à gauche. I. e. un accumulateur sera initialisé et les é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 dans l'ordre dans lequel les éléments sont ajoutés ensemble n'est pas défini. C'est-à-dire: les arguments de fold
forment un monoid .
fold
, contrairement à foldRight
et foldLeft
, n'offre aucune garantie quant à l'ordre dans lequel les éléments de la collection seront traitées. Vous voudrez probablement utiliser fold
, avec sa signature plus restreinte, avec des collections parallèles, où le manque d'ordre de traitement garanti aide la collection parallèle outils pliage d'une manière parallèle. La raison pour changer la signature est similaire: avec les contraintes supplémentaires, il est plus facile de faites un pli parallèle.
pour votre exemple particulier, vous le coderiez de la même façon 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)
d'Accord avec les autres réponses. j'ai pensé à donner un exemple 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)
}
}
Résultat est explicite :
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