Esta característica del lenguaje JavaScript puede ayudarlo a ordenar su código y le brindará una nueva apreciación de cómo funcionan las funciones.
Las funciones curtidas pueden ayudar a que su código JavaScript sea más legible y expresivo. La técnica del curry es ideal cuando se desea dividir una lógica compleja en fragmentos de código más pequeños, autónomos y manejables.
Aprenda todo sobre las funciones de curry en JavaScript, cómo utilizar la técnica de curry de funciones para crear funciones parcialmente aplicadas, así como casos de uso de la vida real tanto para funciones cursadas como para funciones parcialmente aplicadas. funciones.
¿Qué es el curry?
El curry lleva el nombre del matemático Haskell B. Curry, y el concepto deriva del cálculo Lambda. Currying toma una función que recibe más de un parámetro y la divide en una serie de funciones unarias (de un parámetro). En otras palabras, una función curry solo toma un parámetro a la vez.
Un ejemplo básico de curry
A continuación se muestra un ejemplo de una función con curry:
functionbuildSandwich(ingredient1) {
return(ingredient2) => {
return(ingredient3) => {
return`${ingredient1},${ingredient2},${ingredient3}`
}
}
}
El construir sándwich() La función devuelve otra función: una función anónima que recibe el ingrediente2 argumento. Luego, esta función anónima devuelve otra función anónima que recibe ingrediente3. Finalmente, esta última función devuelve el literal de plantilla, una forma de formatear cadenas en JavaScript.
Lo que has creado es una función anidada donde cada función llama a la que está debajo hasta llegar al final. Ahora, cuando llamas construir sándwich() y le pasa un solo parámetro, devolverá la parte de la función cuyos argumentos aún debe proporcionar:
console.log(buildSandwich("Bacon"))
Puede ver en el resultado que buildSandwich devuelve una función:
Para completar la llamada a la función, deberá proporcionar los tres argumentos:
buildSandwich("Bacon")("Lettuce")("Tomato")
Este código pasa "Tocino" a la primera función, "Lechuga" a la segunda y "Tomate" a la última función. En otras palabras, el construir sándwich() La función realmente se divide en tres funciones, y cada función recibe solo un parámetro.
Si bien es perfectamente válido curry usando las funciones tradicionales, todo el anidamiento puede volverse bastante feo cuanto más profundo sea. Para solucionar esto, puedes usar funciones de flecha y aprovechar su sintaxis más limpia:
const buildMeal = ingred1 =>ingred2 =>ingred3 =>
`${ingred1}, ${ingred2}. ${ingred3}`;
Esta versión refactorizada es más concisa, una ventaja de usar funciones de flecha versus funciones regulares. Puedes llamar a la función de la misma manera que lo hiciste con la anterior:
buildMeal("Bacon")("Lettuce")("Tomato")
Funciones de curry parcialmente aplicadas
Las funciones parcialmente aplicadas son un uso común del curry. Esta técnica implica proporcionar sólo los argumentos necesarios a la vez (en lugar de proporcionar todos los argumentos). Siempre que invoca una función pasando todos los parámetros requeridos, dice que ha "aplicado" esa función.
Veamos un ejemplo:
const multiply = (x, y) => x * y;
A continuación se muestra la versión al curry de multiplicar:
const curriedMultiply = x =>y => x * y;
El curryMultiplicar() La función recibe el X argumento para la primera función y y para la segunda función, luego multiplica ambos valores.
Para crear la primera función parcialmente aplicada, llame curryMultiple() con el primer parámetro y asignamos la función devuelta a una variable:
const timesTen = curriedMultiply(10)
En este punto, el código ha "aplicado parcialmente" la curryMultiplicar() función. Así que cuando quieras llamar veces diez(), solo necesita pasarle un número y el número se multiplicará automáticamente por 10 (que se almacena dentro de la función aplicada):
console.log(timesTen(8)) // 80
Esto le permite desarrollar una única función compleja creando múltiples funciones personalizadas a partir de ella, cada una con su propia funcionalidad bloqueada.
Eche un vistazo a un ejemplo que se acerca más a un caso de uso real de desarrollo web. Abajo tienes un actualizarElemText() función que toma el valor de un elemento identificación en la primera llamada, el contenido en la segunda llamada, y luego actualiza el elemento según el identificación y el contenido que le proporcionaste:
const updateElemText = id = content
=> document.querySelector(`#${id}`).textContent = content// Lock the element's id into the function:
const updateHeaderText = updateElemText('header')
// Update the header text
updateHeaderText("Hello World!")
Composición de funciones con funciones al curry
Otro uso común del curry es la composición de funciones. Esto le permite llamar a funciones pequeñas, en un orden específico, y combinarlas en una función única y más compleja.
Por ejemplo, en un sitio web de comercio electrónico hipotético, aquí hay tres funciones que quizás quieras ejecutar una tras otra (en orden preciso):
const addCustomer = fn =>(...args) => {
console.log("Saving customer info")
return fn(...args)
}const processOrder = fn =>(...args) => {
console.log(`processing order #${args[0]}`)
return fn(...args);
}
let completeOrder = (...args) => {
console.log(`Order #${[...args].toString()} completed.`);
}
Tenga en cuenta que este código utiliza el dejar palabra clave para definir el orden completa() función. Esto le permite reasignar un valor a la variable y es parte de cómo funciona el alcance en JavaScript.
A continuación, debe llamar a las funciones en orden inverso (de adentro hacia afuera) porque primero querrá agregar los clientes:
completeOrder = (processOrder(completeOrder));
completeOrder = (addCustomer(completeOrder));
completeOrder("1000")
Esto le dará el siguiente resultado:
Si escribiera las funciones anteriores de la forma habitual, el código se vería así:
functionaddCustomer(...args) {
returnfunctionprocessOrder(...args) {
returnfunctioncompleteOrder(...args) {
// end
}
}
}
Cuando llamas al agregarCliente() funciona y pasa los argumentos, comienza desde adentro y avanza hasta la parte superior de la función.
Convertir una función normal en una función de curry con una función de curry
Si planea utilizar mucho las funciones de curry, puede agilizar el proceso con una función auxiliar.
Esta función convertirá cualquier función normal en una función al curry. Utiliza recursividad para manejar cualquier número de argumentos.
const curry = (fn) => {
return curried = (...args) => {
if (fn.length !== args.length) {
return curried.bind(null, ...args)
}
return fn(...args);
}
}
Esta función aceptará cualquier función escrita estándar que reciba más de un parámetro y devolverá una versión al curry de esa función. Para verlo en acción, utilice esta función de ejemplo que toma tres parámetros y los suma:
const total = (x, y, z) => x + y + z
Para convertir esta función, llame al curry() funcionar y pasar total como argumento:
const curriedTotal = curry(total)
Ahora para llamar a la función, sólo necesitas pasar todos los argumentos:
console.log(curriedTotal(10)(20)(30)) // 60
Más sobre funciones en JavaScript
Las funciones de JavaScript son extremadamente flexibles y las funciones de curry son solo una pequeña parte de eso. Hay muchos otros tipos de funciones, como funciones de flecha, funciones constructoras y funciones anónimas. Familiarizarse con estas funciones y sus componentes es clave para dominar JavaScript.