Creo que he aprendido algunos / muchos / la mayoría de los conceptos básicos que subyacen a la programación funcional en JavaScript. Sin embargo, tengo problemas para leer específicamente el código funcional, incluso el código que he escrito, y me pregunto si alguien puede darme consejos, consejos, mejores prácticas, terminología, etc. que puedan ayudar.
Toma el código a continuación. Escribí este código. Su objetivo es asignar un porcentaje de similitud entre dos objetos, entre say {a:1, b:2, c:3, d:3}
y {a:1, b:1, e:2, f:2, g:3, h:5}
. Produje el código en respuesta a esta pregunta sobre Stack Overflow . Como no estaba seguro exactamente de qué tipo de similitud porcentual preguntaba el afiche, proporcioné cuatro tipos diferentes:
- el porcentaje de las claves en el primer objeto que se puede encontrar en el segundo,
- el porcentaje de los valores en el primer objeto que se puede encontrar en el segundo, incluidos los duplicados,
- el porcentaje de los valores en el primer objeto que se puede encontrar en el segundo, sin duplicados permitidos, y
- el porcentaje de pares {clave: valor} en el primer objeto que se puede encontrar en el segundo objeto.
Comencé con un código razonablemente imperativo, pero rápidamente me di cuenta de que este era un problema muy adecuado para la programación funcional. En particular, me di cuenta de que si podía extraer una función o tres para cada una de las cuatro estrategias anteriores que definían el tipo de característica que buscaba comparar (por ejemplo, las claves o los valores, etc.), entonces podría ser capaz de reducir (perdonar el juego de palabras) el resto del código en unidades repetibles. Ya sabes, manteniéndolo SECO. Entonces cambié a programación funcional. Estoy bastante orgulloso del resultado, creo que es razonablemente elegante, y creo que entiendo lo que hice bastante bien.
Sin embargo, incluso después de haber escrito el código yo mismo y comprender cada parte de él durante la construcción, cuando ahora lo recuerdo, sigo estando un poco desconcertado tanto sobre cómo leer cualquier media línea particular como sobre cómo leerlo. "grok" lo que realmente está haciendo cualquier media línea de código en particular. Me encuentro haciendo flechas mentales para conectar diferentes partes que se degradan rápidamente en un lío de espagueti.
Entonces, ¿alguien puede decirme cómo "leer" algunos de los bits de código más intrincados de una manera concisa y que contribuya a mi comprensión de lo que estoy leyendo? Supongo que las partes que más me atraen son aquellas que tienen varias flechas gruesas en una fila y / o partes que tienen varios paréntesis en una fila. Nuevamente, en esencia, eventualmente puedo descubrir la lógica, pero (espero) que haya una mejor manera de hacerlo rápida y clara y directamente "tomando" una línea de programación funcional de JavaScript.
Siéntase libre de usar cualquier línea de código de abajo, o incluso otros ejemplos. Sin embargo, si quieres algunas sugerencias iniciales de mí, aquí hay algunas. Comience con una razonablemente simple. De cerca de la final del código, hay una que se pasa como parámetro a una función: obj => key => obj[key]
. ¿Cómo se lee y comprende eso? Un ejemplo más es una función completa de cerca del inicio: const getXs = (obj, getX) => Object.keys(obj).map(key => getX(obj)(key));
. La última map
parte me atrapa en particular.
Tenga en cuenta, en este punto en el tiempo que estoy no en busca de referencias a Haskell o notación simbólica abstracta o los fundamentos de currificación, etc. Lo que estoy buscando es frases en inglés que en silencio puede boca mientras mira a una línea de código. Si tiene referencias que aborden específicamente exactamente eso, genial, pero tampoco estoy buscando respuestas que digan que debería ir a leer algunos libros de texto básicos. Lo he hecho y obtengo (al menos una cantidad significativa de) la lógica. También tenga en cuenta que no necesito respuestas exhaustivas (aunque tales intentos serían bienvenidos): incluso las respuestas cortas que proporcionan una forma elegante de leer una sola línea particular de código problemático serían apreciadas.
Supongo que una parte de esta pregunta es: ¿ puedo incluso leer código funcional linealmente, ya sabes, de izquierda a derecha y de arriba a abajo? ¿O uno se ve obligado a crear una imagen mental de cableado tipo espagueti en la página de código que definitivamente no es lineal? Y si uno debe hacer eso, todavía tenemos que leer el código, entonces, ¿cómo tomamos texto lineal y conectamos los espaguetis?
Cualquier consejo sería apreciado.
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
fuente