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 múltiples argumentos en una serie de funciones, cada una con un solo argumento. En esencia, esto permite almacenar funciones en variables y crear funciones que devuelven funciones.
Si bien puede parecer un concepto extraño al principio, es una técnica poderosa que puede ser muy útil a veces. En este tutorial, te mostraré cómo aprovechar las ventajas de la función que se realiza en Swift.
Antes de definir nuestras propias funciones personalizadas, primero le mostraré un ejemplo simple de cómo hacer curry en Swift usando clases.
Abra Xcode, cree un nuevo área de juegos para iOS o OS X y agregue el siguiente código:
clase Car var speed = 0 func accelerateBy (factor: Int) -> Int speed + = factor return speed let car1 = Car ()
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
. Podemos llamar al acelerar, por (_ :)
método de nuestro Coche
instancia con el siguiente código:
car1.accelerateBy (10)
Sin embargo, existe otra forma de ejecutar este método mediante el uso de la función de curry. En el ejemplo anterior, usted llama al método directamente en car1
A pesar del método realmente definido en el Coche
clase. El método que hemos escrito no es específico de la car1
ejemplo, sino más bien la Coche
clase. Cuando llamas a este método, lo que realmente está sucediendo es que Swift primero va al Coche
clase, recupera el acelerar, por (_ :)
método, le dice al método qué instancia se está utilizando y luego ejecuta un método modificado específico para esa instancia. Para mostrarle cómo funciona esto, agregue la siguiente línea a su área de juegos:
Car.accelerateBy (car1)
Lo que estamos haciendo aquí es acceder a la acelerar, por (_ :)
método de la Coche
clase y paso, como parámetro, en qué instancia queremos que se ejecute esta función. En la barra lateral de tu área de juegos, puedes ver que el resultado de este método es otra función..
Que es esto (Función) el resultado representa es en realidad un nuevo acelerar, por (_ :)
método específico para el car1
ejemplo. Esta función devuelta es única en que específicamente hace referencia a car1
es velocidad
propiedad en lugar del método genérico que definió anteriormente, que puede hacer referencia a la velocidad
propiedad de cualquier Coche
ejemplo.
Como es de esperar, podemos pasar nuevos parámetros a esta función devuelta para ejecutarla como lo hacemos normalmente. Agregue la siguiente línea de código a su área de juegos:
Car.accelerateBy (car1) (10)
Con este código, pasamos 10
como un parámetro en el único acelerar, por (_ :)
método y obtener car1
La velocidad actual devolvió como resultado.
¡Felicidades! Acabas de aprovechar la función de curry en Swift por primera vez..
Además de curry juntos múltiples funciones, la Función El resultado de que su código está regresando también se puede almacenar en una variable. Esto le permite almacenar y reutilizar rápidamente el acelerar, por (_ :)
método específico para su car1
ejemplo. Agrega las siguientes líneas a tu patio de recreo:
dejar a = Car.accelerateBy (car1) a (10) a (20) a (30)
Puedes ver esa variable una
Ahora se comporta como cualquier otra función definida globalmente. La ventaja es que es específico para un determinado Coche
instancia, que se puede definir en tiempo de ejecución en lugar de tiempo de compilación. En su área de juegos, puede ver los resultados esperados que se muestran en la barra lateral.
Por último, le mostraré cómo puede devolver una función desde otra función reimplementando el comportamiento de Coche
clase que acabamos de ver. Vamos a hacer esto definiendo una función que devuelve otra función. En tu código, esta función podría verse algo como esto:
func someFunction (input: AnyObject) -> (AnyObject) -> AnyObject // Hacer cosas para devolver una función
Definimos la someFunction (_ :)
función, que acepta una Cualquier objeto
parámetro y devuelve otra función que también acepta una Cualquier objeto
parámetro que devuelve un Cualquier objeto
resultado. Este tipo de definición de función puede parecer muy confuso y desalentador al principio. Para simplificarlo, podemos aprovechar el tipografías
palabra clave en Swift para asignar un nuevo nombre a cualquier tipo de datos.
Agregue el siguiente código a su área de juegos:
typealias IntFunction = (Int) -> Int func accelerationForCar (auto: Car) -> IntFunction return Car.accelerateBy (car) deja newA = accelerationForCar (car1) newA (10)
Mediante el uso tipografías
para asignar el nombre de IntFunction
al (Int) -> Int
tipo de datos, hemos simplificado en gran medida la accelerationForCar (_ :)
definición de la función. los (Int) -> Int
tipo de datos simplemente representa una función que acepta una En t
parámetro y devuelve un En t
valor.
Esta nueva función utiliza el comportamiento incorporado del Coche
clase para devolver un IntFunction
Objeto que luego puede ser almacenado en una variable y usado como lo hicimos antes.
Si bien el comportamiento de curry de la función incorporada en Swift es muy útil, es posible que desee crear sus propias funciones que no estén relacionadas con las clases. Para esta parte del tutorial, primero vamos a usar el ejemplo de una función que multiplica otro número por un valor constante.
Imagina que deseas crear una función que acepte un solo número de entrada y la multiplique por 5. Esta función simple podría tener este aspecto:
func multiplyBy5 (a: Int) -> Int return a * 5
Ahora imagina que necesitas una función similar, pero la necesitas para multiplicar por 10 en lugar de 5. Luego necesitas otra función para multiplicar por 20. Mientras que puedes crear tres funciones similares y nombrarlas multiplicarby5
, multiplicar por 10
, y multiplicar por 120
, Esto podría ser manejado mucho mejor usando la función currying.
Agregue el siguiente fragmento de código a su patio de recreo:
func multiplyBy (a: Int) -> IntFunction func nestedMultiply (b: Int) -> Int return a * b return nestedMultiply multiplyBy (10) (20) let multiplyBy5 = multiplyBy (5) multiplyBy5 (4)
Definimos la multiplicar por(_:)
función que acepta un En t
Como su único parámetro y devuelve 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 pueda ejecutarse fuera del alcance de la multiplicar por(_:)
función y tiene acceso a la una
parámetro de entrada.
Las tres líneas debajo de la definición de la función son ejemplos simples de cómo se pueden combinar las funciones.
Si bien puede crear funciones para hacer curry usando funciones anidadas, también puede crearlas usando cierres o definiendo múltiples conjuntos de parámetros. Como ejemplo, agregue el siguiente fragmento de código a su área de juegos:
func add (a: Int) -> IntFunction return b in a + b permite add2 = add (2) add2 (4) func restar (a: Int) (b: Int) -> Int return b - a vamos a restar5 = restar (5) restar5 (b: 8)
Como puede ver, estas dos nuevas funciones se pueden distribuir juntas de la misma manera que todas las demás funciones se han descrito en este tutorial. La única excepción es que, con la función definida con dos conjuntos de parámetros, debe nombrar explícitamente el segundo parámetro.
No hay límite para la cantidad de niveles de funciones que puede implementar dentro de su código. El siguiente código muestra un ejemplo de tres funciones al curry y cómo difiere en una sola función con tres parámetros.
func multiply (a: Int, b: Int, c: Int) -> Int return a * b * c func multiply (a: Int) -> (Int) -> IntFunction func nestedMultiply1 (b: Int) - > IntFunction func nestedMultiply2 (c: Int) -> Int return a * b * c return nestedMultiply2 return nestedMultiply1 multiplicar (4, 5, 6) multiplicar (4) (5) (6)
La principal diferencia entre estas dos funciones de multiplicación es que la versión al curry se puede pausar y almacenar de manera efectiva en una variable después de que se haya procesado el primer o el segundo parámetro. Esto hace que la función sea muy fácil de reutilizar y pasar como un objeto..
La función de curry en Swift es un concepto difícil de comprender, pero, en su esencia, se trata básicamente de dos conceptos clave:
Hay una variedad de formas de combinar funciones y, mientras que solo las En t
El tipo de datos se usó en este tutorial, los mismos procesos se pueden usar con cualquier tipo de datos en sus proyectos Swift. Esto permite que las funciones se almacenen en variables y se usen muchas veces a lo largo de su código.
Como siempre, asegúrese de dejar sus comentarios y comentarios a continuación en los comentarios.