Hace 6 años | Por mr_b a dev.to
Publicado hace 6 años por mr_b a dev.to

Una vez, haciendo una revisión de código de uno de mis compañeros, vi que usaba un bucle for cuando no era necesario (existía una declaración más legible) . Como chiste dije que habría que poner la “tasa bucle for” (for-loop tax) para cada bucle que se usase de forma innecesaria. Sin embargo, ese chiste me hizo pensar por qué la gente usa el bucle for, más propenso a errores, antes que otras soluciones mejores. La conclusión fue que nos enseñan cómo usar los bucles, pero apenas nos enseñan por qué se necesitan.

Comentarios

mr_b

#1 Como dice #2, es más legible lo primero. Más que nada porque te has “comido” la indentación que tenía, y eso es hacer un poco de trampa.

#3 Creo que quizás te refieres a que es más entendible el bucle for, que es a lo que estamos acostumbrados (como dice el artículo). Pero con dos líneas de código, es más legible lo primero que lo segundo con siete. Creo que #4 te lo ha explicado muy bien.

dreierfahrer

#13 Creo que quizás te refieres a que es más entendible el bucle for

O vaya, que no sabes que significa legible... entiendo....

mr_b

#16 Por eso he dicho “creo que igual te refieres…”. Lo de la comprensión lectora debe ir por barrios. Ni te cuento la ortografía.

dreierfahrer

#17 Veo que no entiendes que significa legible...

Legible no es "2 lineas en lugar de 7", legible es que venga un tio que no tiene ni idea de que hace el codigo y vea que hace de un vistazo.

Legible = entendible y no por ti, nada mas.

mr_b

#18 Te lo voy a volver a repetir, que veo que andas un poco lentito: creo que igual te refieres a…”, porque yo estaba especulando; yo ya no estaba hablando de si era legible o no, estaba yendo por otro camino. Pero tú a lo tuyo, campeón.

c

#6 He de reconocerte que no he mirado mucho el tema de programación declarativa. Y seguramente tengas razón porque yo personalmente me he quedado unos segundos pensando que hace el reduce y como lo utiliza, cuando el trozo con el for lo he identificado casi de inmediato.

De todas formas, todavía me quedaría la duda del coste de proceso, aunque para arrays no muy grandes seguramente sea despreciable.

D

#6 con un bucle for, SIEMPRE tienes que pararte a mirar lo que hace, porque no hay dos iguales.

De hecho corres el riesgo de "no ver" algún fallo, como incrementar el contador en un bucle inverso, o usar una variable errónea como índice...

Usando construcciones funcionales necesitarás un proceso de adaptación (aprender qué narices es un reduce, o un foldRight, o un flatMap, o...) pero después lo entenderás todo más rápido porque un reduce siempre es un reduce

buronix

#23 mientras programes para ti mismo, solo tu leas tu código y tus operaciones de bucle sean simples.

No entiendo el sentido, también te puedes equivocar usando el reduce, para que quieres reducir tanto las lineas de código? tampoco va a ser un cambio radical, van a ser bastante pocas, puedo entender tu gusto, pero no puedes comprender que no es lo mas habitual y es de conocimiento reducido?

mr_b

#3 Lo de que usar una función lleva más coste de proceso no es del todo cierto. Podría ser, pero también podría ser que no gracias a que ciertos lenguajes pueden hacer bastante trabajo en tiempo de compilación y no de ejecución, así que el tiempo de ejecución real se vería bastante reducido. Pero, evidentemente, habría que probar en cada caso.

m

#1 Es más legible lo primero.

D

#1 lo más legible es ruby:

sum = array.reduce(:+)

ED209

#5 array.sum si usas Rails (activesupport)

mr_b

#8 WebAssembly se puede generar con cualquier lenguaje de programación, incluido Javascript. Así que no tiene nada que ver que Javascript sea una mierda (que no lo es) con WebAssembly.

Lo de que es para pajilleros y gente con acné ya es bastante más vergonzoso que gracioso, si es eso lo que pretendías.

#5 En WebAssembly no se va a montar un UI ni nada parecido. WebAssembly es el compilado de cualquier lenguaje que lo genere; por lo tanto, las UI (o lo que sea) serán programadas en Javascript, C, C++, D, Rust, Go… En la respuesta a #8 tienes toda la razón, eso sí.

o

#1 Es un problema muy orientado a JavaScript.

El problema es que no toda la gente conoce ES6 lo suficiente como para poder usar las funciones fat arrow y los métodos map y reduce de los arrays.

Obviamente es mucho mejor usar las sintaxis nueva y un transpiler para dispositivos que no lo soporten, pero tampoco entendí el drama cuando leí el articulo en dev.to

Y de postre decir que no hacen mención al rendimiento, seria interesante ver como se comportan los nuevos métodos en los distintos navegadores comparándolo con bucles for tradicionales.

D

#7 javascript, scala, python, java... hasta C++ tiene métodos funcionales

D

#1 Yo creo que no estás acostumbrado al uso de reduce.

D

#1 Totalmente de acuerdo, este artículo solo refleja un gusto personal del autor... llegue a esa linea, vi el churro y me dije pfff...
Hay dos tipos de programadores, a los que les gusta la magia y a quienes no. A mi no me gusta. Es una cuestión de preferencia personal.

A mi me gustan pocas reglas, simples y si añades algo que sea fácil de aprender y de usar.

m

#25 reduce está lejos de ser magia. Es simplemente una reducción de una secuencia de valores a un solo valor de resultado, aplicando la misma función al par de valores [resultado parcial, siguiente valor] en cada paso.

Por lo tanto, array.reduce((total, current) => total + current, 0) lo que hará será:

((((0 + 1) + 2) + 3) ... + n)

Vamos, lo mismo que hace el bucle for pero sin tener que preocuparse de tener que inspeccionar el código para encontrar qué variables se definen, qué variables se usan y cómo. Las reglas de la programación imperativa como las que rigen los bucles pueden parecer simples, pero pueden provocar un código innecesariamente complejo muy fácilmente.

D

#26 Esa flecha de que lenguaje es? la de =>... me estuve leyendo por ejemplo, en java, y necesitas un artículo bastante largo para entender lo que hace, de tal forma, que días después de habérmelo leído, ya no lo recuerdo, y soy incapaz de aplicar su versión más potente. Un sólo símbolo implicaba demasiadas cosas a la vez según el contexto.

Si te especializas en un lenguaje, cojonudo, pero si estas todo el día con varios... es un coñazo que sean tan complicados. Todo se puede simplificar con una función.

Yo podría sustituir tu código de arriba, por un bucle for supuestamente complicado, aún así corto y testado, y ponerle un nombre descriptivo. PERO eso son gustos, nada más. Sigo leyéndote y no entiendo nada. Quizás es que desconozco ese lenguage, pero bueno, me leeré el artículo para entender, después de un montón de explicaciones, la maravillosa ventaja de ahorrarte 7 lineas de código.

Esas cosas se las dejo al algoritmo, que si puede ser complejo, pq muchas veces no queda otra. O a la estrutura de datos, el modelo, pero el lenguaje... a mi me gusta poder "traducir" lo más rápido posible. Pero decidir que es una verdadera ventaja es una cuestión de gustos.

Si me justificas la reutilización, cojonudo. Si me justificas la eficacia, cojonudo. Pero cambiar 7 lineas de un código que entiende casi cualquiera que venga de casi cualquier lenguaje, por unas lineas que tengo que empollarme a ver que están haciendo (magia: unos pocos caracteres implican muchísimas cosas y encima cambian según el contexto), no se si es buen negocio.

m

#28 Respecto a =>, yo estaba como tú, no sabía lo que significaba porque yo hace tiempo que no hago nada con Javascript, y hoy he visto por el ejemplo del artículo que así es como se especifica un lambda (una función anónima) en ES7. Pero no me ha costado nada entender qué hace esa línea de código porque he visto reduce ya en muchos lenguajes (como reduce o como foldLeft): Java, Scala, Python, Ruby, Haskell, LISP, Clojure y el funcionamiento es siempre el mismo, y el contexto poco tiene que ver. De hecho, no tiene nada que ver porque la forma de utilizarlo es siempre la misma: secuencia, función, valor inicial. Así que no, sigue sin ser magia según tu definición.

Entiendo lo que dices, pero como otros comentan por aquí, lo atribuyo a la falta de hábito con la programación funcional. Personalmente, después de haber hecho muchísima programación imperativa, muchísima OOP y bastante programación funcional, por poco que me cueste entender un bucle for, siempre me será más sencillo entender un reduce. ¿Cuántas variables se definen antes del bucle que vayan a afectar al bucle? ¿Qué variables cambian dentro del bucle? ¿Para qué van a servir esas variables y que resultado, o resultados va a generar el bucle? Todo eso es necesario procesarlo mentalmente para entender el código. Sin embargo, con reduce tienes una secuencia, una función y un valor inicial, nada más.

Prueba a ver con esta explicación en Javascript, a ver si se entiende mejor de lo que me explico (que ya veo que es mal): https://www.airpair.com/javascript/javascript-array-reduce

Que quede claro que en ningún caso esté diciendo yo que 1 línea siempre sea mejor que 7. Lo que digo es que, con conocimientos básicos de programación funcional, es más legible el reduce que el bucle for. Igual que es más legible un bucle for que un "bucle" en assembler hecho a base de escrituras en registros y saltos condicionales.

D

#30 Ok, es que al tema de que una variable sobreviva a una función, solo le veía utilidad para simular la POO en javascript. Sospecho que total, sobrevive con su valor de una llamada a otra de la función por cada elemento, y current es sobreescrito en cada llamada.

Supongo que tiene utilidad pq al ver el reduce() los que le dais más caña al javascript ya sabéis lo que se intenta hacer. Me has medio convencido, oka. Tiene valor semántico.

D

#26 Es que sigo leyendo y con la documentación delante, me cuesta VER como maneja total y current... como si la función la defines tú, como reduce sabe que "current" es el componente del array... y eso que llevo un rato mirándolo.

El ejemplo de antes lo pillé enseguida, pero para entender el nuevo en su totalidad el código, pq hay "magia", sigo sin pillarlo, tengo que seguir navegando en más y más documentación, si es que lo pillo con suerte.

La propia función reduce se comporta de maneras diferentes según el contexto de la llamada, tienes que leerte bien la documentación para saber que hace en cada caso... ESO ES MAGIA. La primera versión es mucho más simple. si lo que quieres es ahorrarte las variables de recorrido, cojonudo, los iteradores llevan inventados décadas.

m

#29 La reducción es un proceso iterativo. En cada paso, tienes un valor, que es total, y que empieza por el valor inicial (en este caso 0), y tienes otro valor, que es current, y que empieza por ser array[0]. En el primer paso, ejecutas la función pasada como parámetro de la función (en el ejemplo: total + current), y obtienes un valor de retorno. Ese valor de retorno pasa a ser el valor total para el siguiente paso, y current será valor[1]. Así sucesivamente hasta que no queden más índices en el array, y total pasará a ser el valor de retorno de la llamada a reduce.

Esto que he explicado, es siempre así, sean cuales sean los parámetros pasados a reduce. Por lo tanto, el funcionamiento de reduce no depende del contexto, sino de los parámetros, como cualquier otra función. Sigue sin ser magia.

D

#31 No si la reducción se entiende perfecto, el "concepto", pero pillar "cómo" lo está haciendo el lenguaje es más complicado.

m

#33 Toda la razón en eso. De hecho creo que aunque estas maneras funcionales existan, no deberían ser excusa para no entender cómo funcionan "por dentro". Pero una vez entendidas bien, ayudan a escoger mejor la herramienta correcta para cada caso. No siempre se puede aplicar map, filter o reduce pero, cuando se puede, se agradece.

De hecho recuerdo haber aprendido sobre estas cosas en pseudocódigo en la carrera (inmersión, plegado/desplegado, de recursivo a iterativo y viceversa, etc) y en su día no verle la utilidad. Sin embargo a día de hoy soy fan lol

D

#34 Yo si se las vi siempre. De hecho me molestaba como la gente se quejaba y sin embargo te dotan de herramientas cojonudas, de las que incluso tu puedes crear híbridos o cosas nuevas usando o mejorando esas técnicas.

Pero vamos, es la típica función a la que llegas cuando tienes un tiempo en un lenguaje. Es de nivel especialización. Y si, es un ejemplo de magia en un lenguaje. Al menos lo que yo llamo magia. La solución de javascript no me gusta, a mi. No me gusta que las variables sobrevivan a las funciones... es muy confuso, a menos que el ámbito esté muy claro, y si ese ámbito existe, déjalo bien claro. Las clases hacen eso, y aún asi, fuera de la clase no salen. Las cosas "bien recogidas" parea poder seguirles la pista.

Pero si la gente del mundillo de javascript, consideráis a reduce una buena implementación, forma parte de la cultura del lenguaje, te adaptas. Es bueno pq marca un patrón reconocible por todos.

angelitoMagno

Es más legible si conoces la función array.reduce, que lo mismo hay mucha gente programando en Javascript que no la conoce

DaniTC

#19 reduce lleva en Javascript desde hace años con lodash o underscore, pudiendo usarse con json. La gente debería conocerla, es útil.

empanadilla.cosmica

La persona que ha escrito el artículo o es autodidacta o no ha aprendido bien.

Se enseña cuando usar los bucles, se enseña cuando se debe usar un bucle y cuando se debe usar otro y se eneseña como convertir un tipo de bucle en otro.

Se enseña a escribir funciones y cuando se deben usar funciones.

Se enseña recursividad y cuando utilizarla y también se enseña como convertir una función recursiva en iterativa y viceversa.

Otra cosa es que una vez salimos de clase y empezamos a trabajar cojamos vicios, o nos adaptemos a lo que haya donde estemos. El viernes mismo estuve haciendo unos scripts en CSH a riesgo de que los que vengan después de mi se caguen en mis muertos, sencillamente por adaptarme a lo que ya había y que fuera congruente. Y eso sabiendo que escribir para la c-shell está desrecomendado desde hace años.

D

No pagues la tasa del __asm__ __volatile__.

La legibilidad es para maricones.

ochoceros

#27 10100001 10100001 01010011 11101101 00100000 01110011 01100101 11110001 01101111 01110010 00100001 00100001

d

Pero que tasa ni que niño muerto, según el mismo autor, en los comentarios: "As others have stated in this thread: if you need performance go for the loops."

Mister_Lala

Buen consejo, pero sobre todo, no te olvides el where en el delete from

matacca

Donde esté un while(true) que nunca devuelva false, que se quiten los for.

daphoene

Sin entrar a valorar las ventajas o inconvenientes de map o reduce, que no son más que una herramienta, lo que me molesta sobremanera es el aire 'cool' de alguna gente, que necesita imperiosamente pasar de ser un pringado a sentirse importante, y se detiene en cosas tan importantes como esta que es en lo poco que le puede afear a alguien con experiencia un novato. Normalmente es lo que veo suceder todos los días, y me repatea ya un poco.

Cuando he visto el título, estaba de acuerdo, porque imaginaba que el artículo versaba sobre los bucles de toda la vida, que la mayoría no ha aprendido a usar correctamente. Yo hace mucho tiempo, con un par de años de experiencia, pensaba que sí. Me apunté a un curso genérico por mejorar habilidades y me sentí ofendido cuando la profesora me puso a hacer loops. Los fallé casi todos. No porque no funcionara lo que hacía, sino porque no había entendido en profundidad el uso de cada uno en su contexto. Por eso pensaba que esta entrada iba a molar, pero no.

Sobre el tema en cuestión, yo soy fan de KISS, y no de los que llevan la cara pintada. Usa lo que quieras, siempre que tenga sentido y sea homogéneo, no me opongo. Pero no evangelices, que salimos a cuatro gurús por picateclas, y además posiblemente evangelices mal.

D

No deberia primar nunca un buen diseño de clases y métodos que el ahorrarse un par de líneas por conocer mejor la sintaxis del lenguaje. Lo primero es lo importante.

MindPaniC

for in

dreierfahrer

javascript es mierda.

En todos y cada uno de sus sabores.

WebAssembly sera la salvacion.

Javascript es para pajilleros y para gente con acne.

o

#8 Mirad, un dinosaurio.

Javascript es el puto meteorito lol

Javascript es muy mejorable, pero de ahí a decir que es una mierda y que C o Golang en los browsers será la salvación... cuando mayormente hay que seguir exponiendo métodos a JS o usar los que ya ofrece el lenguaje desde WebAssembly

Y no, no tiene puto sentido montar un UI en WebAssembly cuando lo puedes hacer en HTML/JS, no lo digo yo, lo dice John Carmak, que tiene pinta de saber de programación mas que todo Meneame junto...