Credo di aver imparato alcuni / molti / molti dei concetti di base alla base della programmazione funzionale in JavaScript. Tuttavia, ho problemi a leggere codice funzionale, persino il codice che ho scritto, e mi chiedo se qualcuno può darmi suggerimenti, consigli, best practice, terminologia, ecc. Che possano aiutare.
Prendi il codice qui sotto. Ho scritto questo codice. Mira ad assegnare una percentuale di somiglianza tra due oggetti, tra say {a:1, b:2, c:3, d:3}
e {a:1, b:1, e:2, f:2, g:3, h:5}
. Ho prodotto il codice in risposta a questa domanda su Stack Overflow . Poiché non ero sicuro di quale tipo di percentuale di somiglianza ci fosse nel poster, ho fornito quattro tipi diversi:
- la percentuale delle chiavi nel primo oggetto che si trova nel 2 °
- la percentuale dei valori nel primo oggetto che si trova nel 2 °, inclusi i duplicati,
- la percentuale dei valori nel primo oggetto che si trova nel 2 °, senza duplicati consentiti, e
- la percentuale di coppie {chiave: valore} nel primo oggetto che si trova nel 2 ° oggetto.
Ho iniziato con un codice ragionevolmente imperativo, ma ho subito capito che si trattava di un problema adatto alla programmazione funzionale. In particolare, mi sono reso conto che se potevo estrarre una funzione o tre per ognuna delle quattro strategie sopra descritte che definivano il tipo di funzionalità che stavo cercando di confrontare (es. Le chiavi, o i valori, ecc.), Allora potrei essere in grado di ridurre (perdonare il gioco di parole) il resto del codice in unità ripetibili. Sai, tenerlo ASCIUTTO. Così sono passato alla programmazione funzionale. Sono piuttosto orgoglioso del risultato, penso sia ragionevolmente elegante, e penso di capire cosa ho fatto abbastanza bene.
Tuttavia, pur avendo scritto il codice da solo e comprendendone ogni parte durante la costruzione, quando ora guardo indietro su di esso, continuo ad essere più che un po 'sconcertato sia a leggere qualsiasi particolare semiretta, sia come "ingannare" ciò che ogni particolare semiretta di codice sta effettivamente facendo. Mi trovo a fare frecce mentali per collegare diverse parti che si degradano rapidamente in un mucchio di spaghetti.
Quindi qualcuno può dirmi come "leggere" alcuni dei bit di codice più contorti in un modo che è sia conciso e che contribuisce alla mia comprensione di ciò che sto leggendo? Immagino che le parti che mi danno di più siano quelle che hanno più frecce grosse di fila e / o parti che hanno parecchie parentesi in fila. Di nuovo, al loro interno, posso finalmente capire la logica, ma (spero) ci sia un modo migliore per andare rapidamente e chiaramente e direttamente "prendendo in considerazione" una linea di programmazione JavaScript funzionale.
Sentiti libero di usare qualsiasi riga di codice dal basso, o anche altri esempi. Tuttavia, se vuoi qualche suggerimento iniziale da parte mia, eccone alcuni. Inizia con uno ragionevolmente semplice. Da vicino alla fine del codice, c'è questo che viene passato come parametro a una funzione: obj => key => obj[key]
. Come si legge e si capisce? Un esempio più lungo è una funzione completa da vicino all'inizio: const getXs = (obj, getX) => Object.keys(obj).map(key => getX(obj)(key));
. L'ultima parte di% co_de mi fa in particolare.
Nota bene, al momento sono non in cerca di riferimenti a Haskell o alla notazione astratta simbolica o ai fondamenti del curry, ecc. Cosa sono em> cercare è frasi in inglese che posso tacere a bocca aperta mentre osservo una riga di codice. Se hai riferimenti specifici che rispondono esattamente a questo, ottimo, ma non sto cercando risposte che dicano che dovrei andare leggi alcuni libri di testo di base. L'ho fatto e ho ottenuto (almeno una parte significativa) la logica. Inoltre, non ho bisogno di risposte esaurienti (anche se tali tentativi sarebbero graditi): anche le risposte brevi che forniscono un modo elegante di leggere una singola riga di codice altrimenti problematico sarebbero apprezzate.
Suppongo che una parte di questa domanda sia: Può leggo anche il codice funzionale in modo lineare, sai, da sinistra a destra e dall'alto verso il basso? O è quasi obbligato a creare un'immagine mentale del cablaggio simile a spaghetti sulla pagina del codice che è decisamente non lineare? E se uno deve farlo, dobbiamo ancora leggere il codice, quindi come facciamo a prendere testo lineare e cablare gli spaghetti?
Qualche consiglio sarebbe apprezzato.
const obj1 = { a:1, b:2, c:3, d:3 };
const obj2 = { a:1, b:1, e:2, f:2, g:3, h:5 };
// x or X is key or value or key/value pair
const getXs = (obj, getX) =>
Object.keys(obj).map(key => getX(obj)(key));
const getPctSameXs = (getX, filter = vals => vals) =>
(objA, objB) =>
filter(getXs(objB, getX))
.reduce(
(numSame, x) =>
getXs(objA, getX).indexOf(x) > -1 ? numSame + 1 : numSame,
0
) / Object.keys(objA).length * 100;
const pctSameKeys = getPctSameXs(obj => key => key);
const pctSameValsDups = getPctSameXs(obj => key => obj[key]);
const pctSameValsNoDups = getPctSameXs(obj => key => obj[key], vals => [...new Set(vals)]);
const pctSameProps = getPctSameXs(obj => key => JSON.stringify( {[key]: obj[key]} ));
console.log('obj1:', JSON.stringify(obj1));
console.log('obj2:', JSON.stringify(obj2));
console.log('% same keys: ', pctSameKeys (obj1, obj2));
console.log('% same values, incl duplicates:', pctSameValsDups (obj1, obj2));
console.log('% same values, no duplicates: ', pctSameValsNoDups(obj1, obj2));
console.log('% same properties (k/v pairs): ', pctSameProps (obj1, obj2));
// output:
// obj1: {"a":1,"b":2,"c":3,"d":3}
// obj2: {"a":1,"b":1,"e":2,"f":2,"g":3,"h":5}
// % same keys: 50
// % same values, incl duplicates: 125
// % same values, no duplicates: 75
// % same properties (k/v pairs): 25