Una mirada entre bastidores a Mapa, Filtro y Reducir en Swift

Una función toma alguna entrada, le hace algo y crea una salida. Una función tiene una firma y un cuerpo. Si le da la misma entrada a una función, siempre obtendrá la misma salida. En resumen, esa es una definición de la función .

Ahora hablaremos más sobre las funciones analizándolas más de cerca. Exploraremos funciones de orden superior en Swift. Una función que toma otra función como entrada o devuelve una función se llamauna función de orden superior .

En Swift, jugamos con mapa, filtramos, reducimos todos los días. Cuando usamos estas funciones, parece mágico. En este punto, es posible que no tenga una idea de lo que sucede detrás de escena. Mapear, filtrar y reducir el trabajo a través de las ideas y enfoques de la programación funcional. Aunque Swift no es un lenguaje funcional puro, te permite hacer cosas funcionales.

Ahora veamos uno por uno lo que les está sucediendo en segundo plano. Primero implementaremos las versiones básicas de estas funciones para algunos tipos de datos particulares, luego intentaremos implementar una versión genérica.

Función de mapa

Digamos que tenemos una matriz de enteros y necesitamos escribir una función que devuelva una nueva matriz después de agregar algún valor delta a cada elemento de la matriz original. Podemos escribir fácilmente una función para esto usando un bucle for simple como el siguiente:

Ahora necesitamos otra función que devuelva una nueva matriz duplicando cada elemento de la matriz original. Para esto, podemos implementarlo como a continuación:

Si miramos las dos funciones anteriores, podemos encontrar que básicamente hacen lo mismo. Solo la funcionalidad dentro del bucle for es diferente. Ambos toman una matriz Integer como entrada, transforman cada elemento usando un bucle for y devuelven una nueva matriz. Entonces, básicamente, lo principal es transformar cada elemento en algo nuevo.

Dado que Swift admite funciones de orden superior, podemos escribir una función que tomará una matriz de enteros, transformará la función como entrada y devolverá una nueva matriz aplicando la función de transformación a cada elemento de la matriz original.

Pero aún así, hay un problema con lo anterior: solo devuelve una matriz de enteros. Si tenemos el requisito de convertir la matriz de enteros de entrada en una matriz de cadenas, por ejemplo, entonces no podemos hacer eso con esta función. Para hacer eso, necesitamos escribir una función genérica que funcione para cualquier tipo.

Podemos implementar una función genérica en una extensión Array como esta:

  1. Declarar una función de mapa en la extensión de matriz que trabaja con un tipo genérico T .
  2. La función toma una función de tipo (Elemento) -> ; T como entrada
  3. Declare una matriz de resultados vacía que contiene los datos del tipo T dentro de la función.
  4. Implemente un bucle for que se repita a sí mismo y llame a la función de transformación para convertir el elemento al tipo T
  5. Agregue el valor convertido en la matriz resultante

Así es como funciona la función de mapa en Swift. Si necesitamos implementar el mapafunción , entonces lo implementaríamos como arriba. Entonces, básicamente, no hace que ocurra ninguna magia en una matriz; podríamos haber definido fácilmente la función por nosotros mismos.

Función de filtro

Supongamos que tenemos una matriz de enteros y queremos mantener solo los números pares en la matriz. Podemos implementar esto usando un bucle for simple:

Ahora nuevamente, digamos que tenemos una matriz de cadenas que representan los nombres de archivos de clase de un proyecto y queremos mantener solo el . archivos rápidos . Esto también se puede hacer con un solo bucle como el siguiente:

Si observamos de cerca la implementación de las dos funciones anteriores, podemos entender que básicamente hacen lo mismo, solo que el tipo de datos es diferente para las dos matrices. Podemos generalizar esto implementando una función de filtro genérica, que toma una matriz y una función como entrada, y dependiendo de la salida de la función includeElement , decide si agregar el elemento en la matriz resultante.

Reducir función

Supongamos que tenemos una matriz de números enteros y queremos implementar dos funciones que devuelven la suma y el producto de los elementos. Podemos implementar esto usando un bucle for simple:

Ahora, en lugar de tener una matriz de enteros, digamos que tenemos una matriz de cadenas y queremos concatenar todos los elementos de la matriz:

Las tres funciones básicamente hacen lo mismo. Toman una matriz como entrada, inicializan una variable resultante, iteran sobre la matriz y actualizan la variable resultante.

Desde aquí podemos implementar una función genérica que debería funcionar para todos. Para hacer esto, necesitamos el valor inicial de la variable resultante y la función para actualizar esa variable en cada iteración.

Entonces podemos implementar la función genérica con la siguiente definición:

La implementación anterior es genérica para cualquier matriz de entrada de tipo [Elemento]. Se calculará un resultado de tipo T . Para funcionar, necesita un valor inicial de tipo T para asignar a una variable resultante. Luego, necesita una función de tipo (T, Elemento) -> T que se usará dentro del bucle for en cada iteración para actualizar la variable resultante.

¡Gracias por leer!