Questa è una risposta supplementare per aiutare a spiegare mappe e pieghe. Per gli esempi di seguito, userò questa lista. Ricorda, questa lista è immutabile, quindi non cambierà mai:
var numbers = [1, 2, 3, 4, 5]
Userò i numeri nei miei esempi perché portano a un codice di facile lettura. Ricorda però che le pieghe possono essere usate per qualsiasi cosa possa essere usata per un ciclo imperativo tradizionale.
Una mappa prende una lista di qualcosa, e una funzione, e restituisce una lista che è stata modificata usando la funzione. Ogni elemento viene passato alla funzione e diventa qualsiasi cosa restituisca la funzione.
L'esempio più semplice di questo è semplicemente l'aggiunta di un numero a ciascun numero in un elenco. Userò pseudocodice per renderlo indipendente dal linguaggio:
function add-two(n):
return n + 2
var numbers2 =
map(add-two, numbers)
Se hai stampato numbers2
, vedresti [3, 4, 5, 6, 7]
che è la prima lista con 2 aggiunti a ciascun elemento. Si noti che la funzione add-two
è stata data a map
da utilizzare.
Fold sono simili, tranne per il fatto che la funzione che ti viene richiesta deve prendere 2 argomenti. Il primo argomento è solitamente l'accumulatore (in una piega a sinistra, che è il più comune). L'accumulatore è il dato che viene passato durante il ciclo. Il secondo argomento è l'elemento corrente dell'elenco; proprio come sopra per la funzione map
.
function add-together(n1, n2):
return n1 + n2
var sum =
fold(add-together, 0, numbers)
Se hai stampato sum
vedresti la somma dell'elenco di numeri: 15.
Ecco quali sono gli argomenti a fold
do:
-
Questa è la funzione che stiamo dando la piega. La piega passerà la funzione l'accumulatore corrente e l'elemento corrente della lista. Qualunque funzione restituisca la funzione diventerà il nuovo accumulatore, che verrà passato alla funzione la volta successiva. Questo è il modo in cui "ricordi" i valori quando fai un ciclo in stile FP. Gli ho dato una funzione che prende 2 numeri e li aggiunge.
-
Questo è l'accumulatore iniziale; ciò che l'accumulatore inizia come prima che vengano elaborati tutti gli elementi nell'elenco. Quando sommi i numeri, qual è il totale prima di aver aggiunto tutti i numeri insieme? 0, che ho passato come secondo argomento.
-
Infine, come per la mappa, passiamo anche all'elenco dei numeri da elaborare.
Se le pieghe non hanno ancora senso, prendi in considerazione questo. Quando scrivi:
# Notice I passed the plus operator directly this time,
# instead of wrapping it in another function.
fold(+, 0, numbers)
In pratica stai mettendo la funzione passata tra ogni elemento della lista e aggiungi l'accumulatore iniziale a sinistra oa destra (a seconda che si tratti di una piega a sinistra oa destra), quindi:
[1, 2, 3, 4, 5]
diventa:
0 + 1 + 2 + 3 + 4 + 5
^ Note the initial accumulator being added onto the left (for a left fold).
Quale è uguale a 15.
Usa un map
quando vuoi trasformare una lista in un'altra lista, della stessa lunghezza.
Usa un fold
quando vuoi trasformare una lista in un singolo valore, come sommare un elenco di numeri.
Come ha sottolineato @Jorg nei commenti, il "valore singolo" non deve essere qualcosa di semplice come un numero; potrebbe essere qualsiasi singolo oggetto, incluso un elenco o una tupla! Il modo in cui avevo effettivamente fatto clic per me era definire una mappa in termini di una piega. Nota come l'accumulatore è una lista:
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)
Onestamente, una volta capito, ti renderai conto che quasi tutti i cicli possono essere sostituiti da una piega o da una mappa.