Je crois que j'ai appris certains / beaucoup / la plupart des concepts de base sous-jacents à la programmation fonctionnelle en JavaScript. Cependant, j'ai du mal à lire spécifiquement le code fonctionnel, même le code que j'ai écrit, et je me demande si quelqu'un peut me donner des conseils, des conseils, des meilleures pratiques, de la terminologie, etc. qui peuvent vous aider.
Prenez le code ci-dessous. J'ai écrit ce code. Il vise à attribuer un pourcentage de similitude entre deux objets, entre dire {a:1, b:2, c:3, d:3}
et {a:1, b:1, e:2, f:2, g:3, h:5}
. J'ai produit le code en réponse à cette question sur Stack Overflow . Parce que je n'étais pas sûr du type de pourcentage de similitude que l'affiche demandait, j'ai fourni quatre types différents:
- le pourcentage des clés du 1er objet que l'on peut trouver dans le 2ème,
- le pourcentage des valeurs du 1er objet que l'on peut trouver dans le 2e, y compris les doublons,
- le pourcentage des valeurs du 1er objet que l'on peut trouver dans le 2e, sans doublons autorisés, et
- le pourcentage de paires {key: value} dans le 1er objet que l'on peut trouver dans le 2ème objet.
J'ai commencé avec un code raisonnablement impératif, mais j'ai rapidement réalisé que c'était un problème bien adapté à la programmation fonctionnelle. En particulier, je me suis rendu compte que si je pouvais extraire une fonction ou trois pour chacune des quatre stratégies ci-dessus qui définissaient le type de fonctionnalité que je cherchais à comparer (par exemple, les touches ou les valeurs, etc.), alors je pourrais être capable de réduire (pardonner le jeu de mots) le reste du code en unités répétables. Vous savez, le garder au SEC. Je suis donc passé à la programmation fonctionnelle. Je suis assez fier du résultat, je pense que c'est assez élégant et je pense que je comprends assez bien ce que j'ai fait.
Cependant, même après avoir écrit le code moi-même et en avoir compris chaque partie pendant la construction, quand j'y repense maintenant, je continue d'être un peu déconcerté à la fois comment lire une demi-ligne particulière, ainsi que comment "grok" ce que fait une demi-ligne particulière de code. Je me retrouve à faire des flèches mentales pour connecter différentes parties qui se dégradent rapidement en un gâchis de spaghettis.
Alors, quelqu'un peut-il me dire comment "lire" certains des morceaux de code les plus compliqués d'une manière à la fois concise et qui contribue à ma compréhension de ce que je lis? Je suppose que les parties qui m'obtiennent le plus sont celles qui ont plusieurs grosses flèches d'affilée et / ou des pièces qui ont plusieurs parenthèses d'affilée. Encore une fois, dans leur cœur, je peux éventuellement comprendre la logique, mais (j'espère) il existe une meilleure façon de procéder rapidement et clairement et directement "en prenant" une ligne de programmation JavaScript fonctionnelle.
N'hésitez pas à utiliser n'importe quelle ligne de code ci-dessous, ou même d'autres exemples. Cependant, si vous voulez quelques suggestions initiales de ma part, en voici quelques-unes. Commencez par une solution assez simple. Près de la fin du code, il y a ce qui est passé comme paramètre à une fonction: obj => key => obj[key]
. Comment peut-on lire et comprendre cela? Un exemple plus est une fonction complète de près du début: const getXs = (obj, getX) => Object.keys(obj).map(key => getX(obj)(key));
. La dernière map
partie me touche particulièrement.
S'il vous plaît noter, à ce moment je ne cherche des références à Haskell ou notation symbolique abstraite ou les fondements de corroyage, etc. Ce que je suis à la recherche est phrases en anglais que je peux en silence la bouche tout en regardant une ligne de code. Si vous avez des références qui traitent précisément de cela, tant mieux, mais je ne recherche pas non plus de réponses qui disent que je devrais aller lire certains manuels de base. Je l'ai fait et j'obtiens (au moins une grande partie de) la logique. Notez également que je n'ai pas besoin de réponses exhaustives (bien que de telles tentatives soient les bienvenues): même des réponses courtes qui fournissent une manière élégante de lire une seule ligne particulière de code autrement gênant seraient appréciées.
Je suppose qu'une partie de cette question est: puis- je même lire le code fonctionnel de façon linéaire, vous savez, de gauche à droite et de haut en bas? Ou est-on à peu près obligé de créer une image mentale d'un câblage de type spaghetti sur la page de code qui n'est décidément pas linéaire? Et si l'on doit le faire, nous devons encore lire le code, alors comment prendre du texte linéaire et câbler les spaghettis?
Des conseils seraient appréciés.
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