J'ai appris la différence fondamentale entre foldLeft
etreduceLeft
foldLeft:
- la valeur initiale doit être transmise
réduireGauche:
- prend le premier élément de la collection comme valeur initiale
- lève une exception si la collection est vide
Y a-t-il une autre différence?
Une raison spécifique pour avoir deux méthodes avec des fonctionnalités similaires?
scala
functional-programming
fold
higher-order-functions
Rajesh Pitty
la source
la source
Réponses:
Peu de choses à mentionner ici, avant de donner la vraie réponse:
left
, elle concerne plutôt la différence entre la réduction et le pliageRetour à votre question:
Voici la signature de
foldLeft
(aurait également pu êtrefoldRight
pour le point que je vais faire):Et voici la signature de
reduceLeft
(encore une fois, la direction n'a pas d'importance ici)Ces deux aspects sont très similaires et ont donc causé la confusion.
reduceLeft
est un cas particulier defoldLeft
(ce qui signifie d'ailleurs que vous pouvez parfois exprimer la même chose en utilisant l'un ou l'autre).Lorsque vous appelez
reduceLeft
say on,List[Int]
cela réduira littéralement toute la liste des entiers en une seule valeur, qui sera de typeInt
(ou un super-type deInt
, par conséquent[B >: A]
).Lorsque vous appelez
foldLeft
say on a,List[Int]
il pliera toute la liste (imaginez rouler un morceau de papier) en une seule valeur, mais cette valeur ne doit même pas être liée àInt
(d'où[B]
).Voici un exemple:
Cette méthode prend un
List[Int]
et retourne unTuple2[List[Int], Int]
ou(List[Int], Int)
. Il calcule la somme et renvoie un tuple avec une liste d'entiers et sa somme. Soit dit en passant, la liste est renvoyée à l'envers, car nous l'avons utilisé à lafoldLeft
place defoldRight
.Regardez One Fold pour les gouverner tous pour une explication plus approfondie.
la source
B
est un super-type deA
? Il semble que ceB
devrait être un sous-typeA
et non un super-type. Par exemple, en supposant queBanana <: Fruit <: Food
si nous avions une liste deFruit
s, il semble que cela puisse contenir desBanana
s, mais s'il en contenait,Food
le type serait, n'estFood
-ce pas? Donc, dans ce cas, siB
est un sur-type deA
et qu'il existe une liste contenant à la foisB
s etA
s, la liste doit être de typeB
, nonA
. Pouvez-vous expliquer cet écart?List[Banana]
peut être réduit à un seulBanana
ou à un seulFruit
ou à un seulFood
. Parce queFruit :> Banana
et «Nourriture:> Banane».Banana
peut contenir unFruit
", ce qui n'a pas de sens. Votre explication a un sens - laf
fonction à laquellereduce()
vous passez peut entraîner unFruit
ou unFood
, ce qui signifie queB
la signature doit être une superclasse, pas une sous-classe.reduceLeft
est juste une méthode pratique. C'est équivalent àla source
reducelft
bienfold
fonctionne sur une liste vide alors que cereduce
n'est pas le cas.foldLeft
est plus générique, vous pouvez l'utiliser pour produire quelque chose de complètement différent de ce que vous avez mis à l'origine. Alors quereduceLeft
ne peut produire qu'un résultat final du même type ou super type du type de collection. Par exemple:Le
foldLeft
appliquera la fermeture avec le dernier résultat plié (première fois en utilisant la valeur initiale) et la valeur suivante.reduceLeft
d'autre part, combinera d'abord deux valeurs de la liste et les appliquera à la fermeture. Ensuite, il combinera le reste des valeurs avec le résultat cumulatif. Voir:Si la liste est vide
foldLeft
peut présenter la valeur initiale comme un résultat légal.reduceLeft
en revanche n'a pas de valeur légale s'il ne trouve pas au moins une valeur dans la liste.la source
La raison fondamentale pour laquelle ils sont tous les deux dans la bibliothèque standard de Scala est probablement parce qu'ils sont tous les deux dans la bibliothèque standard de Haskell (appelés
foldl
etfoldl1
). Si cereduceLeft
n'était pas le cas, elle serait très souvent définie comme une méthode pratique dans différents projets.la source
Pour référence, une
reduceLeft
erreur s’applique à un conteneur vide avec l’erreur suivante.Retravailler le code à utiliser
est une option potentielle. Une autre consiste à utiliser la
reduceLeftOption
variante qui renvoie un résultat encapsulé Option.la source
De Principes de programmation fonctionnels à Scala (Martin Odersky):
[par opposition à
reduceLeft
, qui lève une exception lorsqu'il est appelé sur une liste vide.]Le cours (voir la conférence 5.5) fournit des définitions abstraites de ces fonctions, qui illustrent leurs différences, bien qu'elles soient très similaires dans leur utilisation de la correspondance de motifs et de la récursivité.
Notez que
foldLeft
renvoie une valeur de typeU
, qui n'est pas nécessairement le même type queList[T]
, mais ReduceLeft renvoie une valeur du même type que la liste).la source
Pour vraiment comprendre ce que vous faites avec le repli / réduction, vérifiez ceci: http://wiki.tcl.tk/17983 très bonne explication. une fois que vous obtenez le concept de pli, la réduction s'affichera avec la réponse ci-dessus: list.tail.foldLeft (list.head) (_)
la source