Map, reduce y filter en F#
Este es post es una reedición del post de Giovanni Cortés llamado Map, filter y reduce en Swift, te invito a visitarlo.
También existe este post pero relacionado con C#, visítalo aquí.
F# es un gran lenguaje, y unas de las cosas que me gusta de él es que está orientado completamente a la programación funcional. Comparte varias características con lenguajes como Elixir y otras pocas con lenguajes como Swift.
Una de las características es que las funciones son tratadas como tipos, pueden aceptar funciones como parámetros y retornar funciones. A menudo a las funciones que toman como parámetros otras funciones son llamadas funciones de orden superior.
En este artículo vamos a enfocarnos en tres funciones que vienen incluídas en F# y que son muy poderosas cuando queremos manejar colecciones.
Map
Imaginemos que tenemos un arreglo de números enteros y a todos los elementos queremos elevarlo al cuadrado.
Generalmente haríamos una función con un bucle como el siguiente:
La función map
resuelve el problema de transformar los elementos de un arreglo pasándoles una función. Esta función itera sobre cada elemento y a cada uno de ellos les aplica la función que nosotros pasemos como parámetro, esto nos ahorra usar mucho los for…in…do y además de que es más elegante. map
retorna un arreglo de la misma longitud que el arreglo al cual le aplicamos la transformación.
El código anterior quedaría así:
En este caso pasamos la función como una expresión lambda fun x -> x * x
, donde x
es cada elemento del arreglo pasado como parámetro de la expresión, y x * x
es el cuerpo de la función, de esa forma pudimos transformar los elementos del arreglo sin crear ningún bucle.
Filter
Al igual que map
, filter
es una función que itera sobre los arreglos. Como su nombre lo indica, filtra los elementos de un arreglo de acuerdo a la función que nosotros le pasemos.
filter
retorna un arreglo con los elementos filtrados del arreglo original, pudiendo ser de igual longitud, menor o vacío.
Supongamos que tenemos un arreglo que representa los nombres de imágenes con diferentes extensiones y queremos obtener solo los jpg:
Ahora usemos la función filter
:
Al igual que map
, no tuvimos que crear ni un for…in…do, ni tampoco tuvimos que agregar el elemento que estamos filtrando, solamente pasamos nuestra expresión y filter
hace todo por nosotros.
NOT Cabe destacar que F# infiere el tipo de la variable gracias al arreglo original, por eso podemos usar el método EndsWith
a cada elemento porque se sabe que es un tipo cadena.
Reduce
Al contrario que map
y filter
, reduce
nos retorna un solo valor, que es la combinación de los elementos del arreglo al cual le aplicamos la función.
Prosigamos con el ejemplo de los números, si queremos sumar todos los elementos de un arreglo, haríamos algo como esto:
Cuando usamos reduce
, no solamente tenemos que pasar una función, si no también un acumulador, que es el valor inicial de nuestro contador, si es trabajo con enteros generalmente es 0, si son cadenas se pasa una cadena vacía. Depende de lo que quieras hacer.
Ahora el ejemplo con reduce
:
En este caso, el acumulador toma el valor inicial de 0, ese valor se pasa como parámetro a la expresión lambda, al cual le pusimos como nombre acc
. x
es cada elemento del arreglo, y el cuerpo de nuestra lambda es la suma del acumulador y cada elemento del arreglo.
Como ves, esta función es un poco más elaborada, pero una vez que le entiendas, puedes hacer muchas cosas interesantes.
Combinando todo
Ahora que ya sabemos el uso de estas funciones, vamos a crear un pequeño programa donde usaremos las tres al mismo tiempo.
Listo, tenemos nuestro programa funcionando y filtrando las ciudades, sin necesidad de usar bucles, además que gracias al acumulador usado como cadena, podemos imprimir nuestras ciudades en un lindo formato.
Espero te haya convencido de que empieces a usar estas funciones en tu programa, verás cómo vas a ir haciendo un código mucho más elegante y funcional.