La risposta di Tarmil ha già dimostrato la differenza tra i due in modo buono e conciso. Fornirò un esempio che utilizza un tipo di dati un po 'più complesso. (In realtà, se si ignora la nomina poi il mio esempio è una lista collegata, ma si può immaginare come potrebbe essere esteso a qualcosa di molto più complesso.)
Lo scopo di fold
vs foldBack
non è necessariamente evidente quando si calcola un valore scalare, ma quando si inizia a usarlo per costruire strutture dati, diventa chiaro che la maggior parte di tali strutture deve essere costruita in una particolare direzione. Ciò è particolarmente vero se si utilizzano strutture dati immutabili, poiché non si ha la possibilità di costruire un nodo e quindi di aggiornarlo per puntare a un altro nodo.
In questo esempio, ho definito una struttura per un linguaggio di programmazione banale che non fa altro che stampare numeri. Riconosce due istruzioni, Print
e End
. Ogni istruzione di stampa memorizza un puntatore all'istruzione successiva. Pertanto, un programma consiste in una catena di istruzioni, ciascuna orientata al successivo. (La ragione per cui ho usato questo particolare esempio è perché, eseguendo il programma, ne mostri la struttura.)
Il programma utilizza tre diversi metodi di costruzione del programma da un elenco di numeri interi. Il primo, make_list_printer
, è definito in modo ricorsivo senza fold, per dimostrare cosa stiamo cercando di ottenere. Il secondo, make_list_printer_foldBack
, utilizza foldBack
per ottenere lo stesso risultato. Il terzo, make_list_printer_fold
, utilizza fold
per dimostrare come produce il risultato errato.
Ho codificato per lo più in OCaml, non in F #, quindi mi scuso se alcune delle convenzioni di codifica utilizzate di seguito non sono realmente considerate come lo stile corretto in F #. L'ho provato con l'interprete F #, e funziona.
(* Data structure of our mini-language. *)
type prog =
| End
| Print of int * prog
(* Builds a program recursively. *)
let rec make_list_printer = function
| [] -> End
| i :: program -> Print (i, make_list_printer program)
(* Builds a program using foldBack. *)
let make_list_printer_foldBack ints =
List.foldBack (fun i p -> Print (i, p)) ints End
(* Builds a program in the wrong direction. *)
let make_list_printer_fold ints =
List.fold (fun p i -> Print (i, p)) End ints
(* The interpreter for our mini-language. *)
let rec run_list_printer = function
| End ->
printfn ""
| Print (i, program) ->
printf "%d " i;
run_list_printer program
(* Build and run three different programs based on the same list of numbers. *)
let() =
let base_list = [1; 2; 3; 4; 5] in
let a = make_list_printer base_list in
let b = make_list_printer_foldBack base_list in
let c = make_list_printer_fold base_list in
run_list_printer a;
run_list_printer b;
run_list_printer c
L'output che provo quando corro questo è:
1 2 3 4 5
1 2 3 4 5
5 4 3 2 1
concatenare una stringa? –
Prova a utilizzarli per creare una struttura di dati nidificata e vedere cosa succede. –
@JohnPalmer Grazie, ad esempio: 'let res = List.foldBack (+) lista" "' è uguale a 'let res1 = lista |> List.rev |> List.fold (+)" "' –