Estoy tratando de practicar la composición de funciones usando Ramda, pero me pregunto si es exagerado y necesito algunos consejos al respecto.
Dado el objeto de abajo
const articles = [ { title: 'Everything Sucks', url: 'http://do.wn/sucks.html', author: { name: 'Debbie Downer', email: 'debbie@do.wn' } }, { title: 'If You Please', url: 'http://www.geocities.com/milq', author: { name: 'Caspar Milquetoast', email: 'hello@me.com' } } ];Haz una función booleana que diga si una persona determinada escribió alguno de los artículos.
Ejemplo de invocación de función
isAuthor('New Guy', articles) // should return false isAuthor('Debbie Downer', articles) // should return trueMi solución
Primero creo una función para tomar el nombre del autor como se muestra a continuación
const get = _.curry(function(x, obj) { return obj[x]; }); const names = _.map(_.compose(get('name'), get('author'))); // ['Debbie Downer', 'Caspar Milquetoast'] Ahora que tengo names de funciones listos para usar, intentaré construir la función isAuthor y a continuación se muestran dos de mis intentos.
Intento 1: sin composición
const isAuthor = function(name, articles) { return _.contains(name, names(articles)) };Intento 2 con composición
const isAuthor = function(name, articles) { return _.compose( _.contains(name), names )(articles); }Ambos intentos funcionan con resultados correctos, esta pregunta se hace únicamente desde la perspectiva de la programación funcional, ya que soy totalmente nuevo en este dominio y me pregunto qué intento es más favorable que el otro, y espero que esta pregunta no se cierre como una opinión basada, sinceramente pienso que esto no se basa en una opinión, sino que busca una práctica industrial en el mundo de la FP.
También siéntase libre de proporcionar cualquier alternativa a los dos intentos que he hecho, ¡gracias!
Ramda tiene un conjunto de funciones para trabajar con propiedades anidadas. En tu caso podríamos combinar pathEq y any :
pathEq devuelve true si una propiedad en la ruta dada es igual al valor dado.any aplica una función de predicado a cada elemento de una lista hasta que se satisface. La función isAuthor primero toma un nombre y luego devuelve una función que toma una lista:
const {compose, any, pathEq} = R; const isAuthor = compose(any, pathEq(['author', 'name'])); isAuthor('Debbie Downer')(articles); //=> true isAuthor('John Doe')(articles); //=> falsePero esto no es necesariamente mejor que:
const {curry} = R; const isAuthor = curry((x, xs) => xs.some(y => y?.author?.name === x)); isAuthor('Debbie Downer')(articles); //=> true isAuthor('John Doe')(articles); //=> falsePiense en Ramda como una herramienta que lo ayuda a escribir de cierta manera, y no como algo que dicta cómo escribe su código. Ramda (descargo de responsabilidad: soy uno de los fundadores) te permite escribir de una manera más declarativa, usando buenas composiciones y canalizaciones. Pero eso no significa que deba usarlo en todos los lugares donde pueda.
La respuesta simple de Vanilla JS de tuomokar es probablemente todo lo que necesita, pero Ramda tiene herramientas que pueden hacer que parezca más legible para algunos.
Así que podríamos escribir algo como esto:
const isAuthor = (name) => (articles) => includes (name) (map (path (['author', 'name'])) (articles)) const articles = [{title: 'Everything Sucks',url: 'http://do.wn/sucks.html', author: {name: 'Debbie Downer',email: 'debbie@do.wn'}}, {title: 'If You Please', url: 'http://www.geocities.com/milq', author: {name: 'Caspar Milquetoast', email: 'hello@me.com'}}] console .log (isAuthor ('New Guy') (articles)) console .log (isAuthor ('Debbie Downer') (articles)) <script src="//cdnjs.cloudflare.com/ajax/libs/ramda/0.27.1/ramda.min.js"></script> <script>const {includes, map, path} = R </script> Tenga en cuenta que su get está integrado en Ramda como prop , y que sus names se pueden escribir como map (path (['author', 'name'])) .
Podríamos hacer esto sin puntos, por nuestra cuenta o usando una herramienta como http://pointfree.io/ . Podría verse así:
const isAuthor = compose ((o (__, map (path (['author', 'name'])))), contains)Pero me parece mucho menos legible que cualquiera de las otras sugerencias. no me molestaría
Ambas soluciones parecen una exageración, al menos en mi opinión.
Sin usar ninguna biblioteca, una solución podría ser tan simple como esta, por ejemplo:
const isAuthor = (name, articles) => articles.some((article) => article.author.name === name)La programación funcional es genial, pero no significa que debas hacer las cosas innecesariamente complejas.
De sus propuestas, la primera parece mucho más legible que la segunda.