Il s'agit d'une réponse supplémentaire pour expliquer les cartes et les plis. Pour les exemples ci-dessous, je vais utiliser cette liste. N'oubliez pas que cette liste est immuable, elle ne changera donc jamais:
var numbers = [1, 2, 3, 4, 5]
Je vais utiliser des nombres dans mes exemples, car ils conduisent à un code facile à lire. N'oubliez pas cependant que les plis peuvent être utilisés pour tout ce à quoi une boucle impérative traditionnelle peut être utilisée.
Une carte prend une liste de quelque chose et une fonction et renvoie une liste qui a été modifiée à l'aide de la fonction. Chaque élément est passé à la fonction et devient tout ce que la fonction retourne.
L'exemple le plus simple consiste simplement à ajouter un numéro à chaque numéro d'une liste. Je vais utiliser le pseudocode pour le rendre indépendant du langage:
function add-two(n):
return n + 2
var numbers2 =
map(add-two, numbers)
Si vous imprimiez numbers2
, vous verriez [3, 4, 5, 6, 7]
quelle est la première liste avec 2 ajoutés à chaque élément. Notez que la fonction a add-two
été donnée map
à utiliser.
Les plis sont similaires, sauf que la fonction que vous devez leur donner doit prendre 2 arguments. Le premier argument est généralement l'accumulateur (dans un pli gauche, qui sont les plus courants). L'accumulateur correspond aux données transmises lors de la boucle. Le deuxième argument est l'élément actuel de la liste; comme ci-dessus pour la map
fonction.
function add-together(n1, n2):
return n1 + n2
var sum =
fold(add-together, 0, numbers)
Si vous imprimiez, sum
vous verriez la somme de la liste des nombres: 15.
Voici ce que les arguments à fold
faire:
C'est la fonction que nous donnons au pli. Le pli passera la fonction de l'accumulateur actuel et l'élément actuel de la liste. Tout ce que la fonction retourne deviendra le nouvel accumulateur, qui sera transmis à la fonction la prochaine fois. C'est ainsi que vous vous "souvenez" des valeurs lorsque vous bouclez en FP. Je lui ai donné une fonction qui prend 2 nombres et les ajoute.
Ceci est l'accumulateur initial; ce que l'accumulateur démarre comme avant que tous les éléments de la liste soient traités. Lorsque vous additionnez des nombres, quel est le total avant d'avoir ajouté des nombres ensemble? 0, que j'ai passé comme deuxième argument.
Enfin, comme pour la carte, nous passons également la liste des nombres à traiter.
Si les plis n'ont toujours pas de sens, pensez à cela. Lorsque vous écrivez:
# Notice I passed the plus operator directly this time,
# instead of wrapping it in another function.
fold(+, 0, numbers)
Vous placez essentiellement la fonction passée entre chaque élément de la liste et ajoutez l'accumulateur initial à gauche ou à droite (selon qu'il s'agit d'un pli gauche ou droit), donc:
[1, 2, 3, 4, 5]
Devient:
0 + 1 + 2 + 3 + 4 + 5
^ Note the initial accumulator being added onto the left (for a left fold).
Ce qui équivaut à 15.
Utilisez un map
lorsque vous souhaitez transformer une liste en une autre liste, de même longueur.
Utilisez un fold
lorsque vous souhaitez transformer une liste en une seule valeur, comme la somme d'une liste de nombres.
Comme l'a souligné @Jorg dans les commentaires, la "valeur unique" n'a pas besoin d'être quelque chose de simple comme un nombre; il peut s'agir de n'importe quel objet, y compris une liste ou un tuple! La façon dont j'ai fait cliquer les plis pour moi était de définir une carte en termes de pli. Notez comment l'accumulateur est une liste:
function map(f, list):
fold(
function(xs, x): # xs is the list that has been processed so far
xs.add( f(x) ) # Add returns the list instead of mutating it
, [] # Before any of the list has been processed, we have an empty list
, list)
Honnêtement, une fois que vous les comprendrez, vous réaliserez que presque toutes les boucles peuvent être remplacées par un pli ou une carte.