7 days of WordPress plugins, themes & templates - for free!* Unlimited asset downloads! Start 7-Day Free Trial
Advertisement
  1. Code
  2. Swift

Función Currying en Swift

Scroll to top
Read Time: 7 mins

Spanish (Español) translation by Andrea Jiménez (you can also view the original English article)

Introducción

Currying es una característica que se encuentra en la mayoría de los lenguajes de programación modernos. Traduce una sola función con varios argumentos en una serie de funciones, cada una con un argumento. En esencia, esto permite almacenar funciones en variables y crear funciones que retornen funciones.

Aunque al principio puede parecer un concepto extraño, es una técnica poderosa que en ocasiones puede resultar muy útil. En este tutorial, te mostraré cómo aprovechar la función currying en Swift.

1. Función Currying con clases

Antes de definir nuestras propias funciones personalizadas, primero voy a mostrarte un ejemplo sencillo de currying en Swift usando las clases.

Abre Xcode, crea una nueva configuración para iOS u OS X y agrégalo al siguiente código:

Definimos una clase básica con una propiedad y un método o función de instancia. También creamos una instancia de la clase, car1. Con el siguiente código podemos llamar al método accelerateBy(_:) de nuestra instancia Car:

Sin embargo, hay otra forma de ejecutar este método mediante el uso de la función currying. En el ejemplo anterior, llama al método directamente en la instancia car1 a pesar de que el método está realmente definido en la clase Car. El método que hemos escrito no es específico de la instancia car1, sino de la clase Car. Cuando llamas a este método, lo que realmente está sucediendo es que Swift primero va a la clase Car, recupera el método accelerateBy(_:), le informa al método qué instancia se está utilizando y luego ejecuta un método modificado específico para esa instancia. Para mostrarte cómo funciona esto, agrega la siguiente línea a tu configuración:

Lo que estamos haciendo aquí es acceder al método accelerateBy(_:) de la clase Car, y pasar como parámetro en la instancia  que queremos que se ejecute esta función. En la barra lateral de tu configuración, puedes ver que el resultado de este método es otra función.

A new function is returnedA new function is returnedA new function is returned

Lo que representa este resultado de la (Función) es en realidad un nuevo método accelerateBy(_:) específico para la instancia car1. Esta función retornada es única porque hace referencia específicamente a la propiedad speed de la instancia car1 en lugar del método genérico que definiste anteriormente, que puede hacer referencia a la propiedad speed de cualquier instancia de Car.

Como era de esperar, podemos pasar los nuevos parámetros a esta función retornada con el fin de ejecutarla como lo hacemos normalmente. Agrega la siguiente línea de código a tu configuración:

Con este código, pasamos 10 como parámetro al método exclusivo accelerateBy(_:) y obtenemos como resultado la velocidad actual de car1.

Function currying at workFunction currying at workFunction currying at work

¡Felicitaciones! Acabas de aprovechar la función currying en Swift por primera vez.

Además de combinar varias funciones, el resultado de la función que retorna tu código también se puede almacenar en una variable. Esto te permite almacenar y reutilizar rápidamente el método accelerateBy(_:) específico para tu instancia car1. Agrega las siguientes líneas a tu configuración:

Ahora puedes ver que la variable a se comporta como cualquier otra función definida globalmente. La ventaja es que es específico para una instancia de Car en particular, que se puede definir en tiempo de ejecución en lugar de en tiempo de compilación. En tu configuración, puedes ver las salidas esperadas que se muestran en la barra lateral.

Results from stored functionResults from stored functionResults from stored function

Por último, te mostraré cómo puedes retornar una función desde otra función reimplementando el comportamiento de la clase Car. Vamos a hacer esto definiendo una función que retorne otra función. Esta función podría verse así en tu código:

Definimos la función someFunction(_:), la cual acepta un parámetro AnyObject y retorna otra función que también acepta un parámetro AnyObject que retorna un resultado AnyObject. Este tipo de definición de la función puede parecer muy confuso y abrumador al principio. Para simplificarlo, podemos aprovechar la palabra clave typealias en Swift para asignar un nuevo nombre a cualquier tipo de datos.

Agrega el siguiente código a tu configuración:

Al usar typealias para asignar el nombre de IntFunction al tipo de datos (Int) -> Int, hemos simplificado enormemente la definición de la función accelerationForCar(_:). El tipo de datos (Int) -> Int simplemente representa una función que acepta un parámetro Int y retorna un valor Int.

Esta nueva función utiliza el comportamiento integrado de la clase Car para retornar un objeto IntFunction que, luego, puede almacenarse en una variable y usarse como lo hicimos antes.

2. Funciones personalizadas de currying

Es posible que quieras crear tus propias funciones que no estén relacionadas con las clases. Aunque el comportamiento de la función currying integrada en Swift es muy útil. En esta parte del tutorial, vamos a usar el ejemplo de una función que multiplica otro número por un valor constante.

Imagina que quieras crear una función que acepte un solo número de entrada y lo multiplique por 5. Esta función simple podría verse así:

Ahora imagina que necesitas una función similar, pero necesitas que se multiplique por 10 en lugar de 5. Luego necesitas otra función para multiplicar por 20. Si bien puedes crear tres funciones similares y nombrarlas multiplyBy5, multiplyBy10 y multiplyBy20, esto podrías manejarlo mucho mejor usando la función currying.

Agrega el siguiente fragmento de código a tu configuración:

Definimos la función multiplyBy(_:) que acepta un Int como su único parámetro y retorna una función de tipo IntFunction, el tipo de datos que definimos anteriormente en este tutorial. En esta función, definimos otra función, nestedMultiply(_:). Anidamos esta función dentro de la primera para que no se pueda ejecutar fuera del alcance de la función multiplyBy(_:) y tenga acceso al parámetro de entrada a.

Las tres líneas debajo de la definición de la función son ejemplos simples de cómo puedes combinar las funciones de curry.

Custom function currying resultsCustom function currying resultsCustom function currying results

Aunque puedes crear funciones para currying utilizando funciones anidadas, también puedes crearlas mediante cierres o definiendo varios conjuntos de parámetros. Como ejemplo, agrega el siguiente fragmento de código tu configuración:

Como puedes ver, estas dos nuevas funciones se pueden combinar de la misma manera que todas las demás funciones a lo largo de este tutorial. La única excepción es que, con la función definida con dos conjuntos de parámetros, debes asignar explícitamente el nombre del segundo parámetro.

No hay límite en el número de niveles de la función currying que puedes implementar dentro de tu código. El siguiente código te muestra un ejemplo de tres funciones curry y cómo se diferencia de una sola función con tres parámetros.

La principal diferencia entre estas dos funciones de multiplicación es que la versión curry se puede pausar y almacenar de manera efectiva en una variable después de que se haya procesado el primer o segundo parámetro. Esto hace que la función sea muy fácil de reutilizar y pasar como un objeto.

Conclusión

La función de currying en Swift es un concepto difícil de comprender, pero, en esencia, se trata básicamente de dos conceptos clave:

  • La creación de funciones que retornan otras funciones.
  • Reducir funciones con múltiples argumentos en una serie de funciones, cada una con un argumento.

Hay varias formas de combinar las funciones y, aunque en este tutorial solo usamos el tipo de datos Int, se pueden usar los mismos procesos con cualquier tipo de datos en tus proyectos Swift. Esto permite que las funciones se almacenen en las variables y se usen muchas veces en todo el código.

Como siempre, asegúrate de dejar tu opinión y sugerencias en la zona de los comentarios.

Advertisement
Did you find this post useful?
Want a weekly email summary?
Subscribe below and we’ll send you a weekly email summary of all new Code tutorials. Never miss out on learning about the next big thing.
Advertisement
Looking for something to help kick start your next project?
Envato Market has a range of items for sale to help get you started.