Programación Funcional (4): El Poder del Currying

¡Acostúmbrate a escribir juntos! Este es el décimo día de mi participación en el "Nuggets Daily New Plan·Desafío de actualización de abril", haz clic para ver los detalles del evento

En el artículo anterior , se discutieron los fundamentos y el núcleo de la programación funcional y las características de las funciones puras. Esta publicación explorará la asignación de funciones.

que es curry

Una función curry es una función que devuelve una función hasta que se hayan pasado todos los argumentos.

Cómo funciona el curry

Supongamos que tenemos la addfunción

const add = (a, b) => a + b
复制代码

La implementación más simple de curry es hacer que las funciones devuelvan funciones como:

const add = (a) => (b) => a + b
复制代码

El método de uso es el siguiente:

const addOne = add(1) // addOne = (b) => 1 + b
复制代码

Otra implementación, supongamos que tenemos una  curryfunción que toma una función como argumento y luego la procesa:

const add = curry((a, b) => a + b)
复制代码

Como podemos ver, curryes una función que utiliza otra función para retrasar argumentos. Podemos llamarlo así:

const addOne = add(1) // addOne = (b) => 1 + b
复制代码

Primero, lo creamos pasando 1 como primer argumento a la addfunción curry addOne. Esto produce otra función que espera a que se pasen el resto de los argumentos, la lógica de adición no se ejecuta hasta que se pasan todos los argumentos.

addOne(2) // 3
复制代码

Pase 2 (como b) a addOne; realice la lógica 1+2.

Resumen rápido:
curryuna función toma una función y hace que sus argumentos sean perezosos.

¿Por qué curry?

Currying hará nuestro código:

  1. más claro
  2. Paso de parámetros menos repetitivo y código menos detallado
  3. mejor combinación
  4. mejor repetibilidad

Por qué curry puede mejorar nuestro código

Principalmente, algunas funciones toman datos de "configuración" como entrada
. Si tenemos funciones que aceptan parámetros de "configuración", será mejor que los cursemos, porque estos parámetros de "configuración" pueden usarse una y otra vez. Por ejemplo, digamos que tenemos una  translatorfunción que acepta un localetexto para traducir text:

const translator = (locale, text) => {/*translation*/}
复制代码

El uso es el siguiente:

translator('fr', 'Hello')
translator('fr', 'Goodbye')
translator('fr', 'How are you?')
复制代码

每次我们调用translator时,我们都应该传递locale 和 text。这是多余且不干净的,在每次调用中都会传递locale
我们可以柯里化translator函数:

const translator = curry((locale, text) => {/*translation*/})
const inFrench = translator('fr') 
复制代码

现在,inFrenchfr作为语言环境传递给柯里化的translator函数,并等待提供text。我们可以这样使用它:

inFrench('Hello')
inFrench('Goodbye')
inFrench('How are you?')
复制代码

柯里化确实帮一个大忙,我们不需要每次都指定区域设置,因为柯里化,inFrench具有区域设置了。

在柯里化之后——在这个具体的例子中。代码变得:

  1. 更加干净了
  2. 不那么冗长,不那么多余

因为我们把“配置”和实际的“数据”分开了。这在许多情况下都非常方便。

在实际工作中

在实践中,我们有动态语言环境(每个用户都有不同的语言),可能是fr、en、de或其他。因此,我们最好将inFrench重命名为translatetranslate可以加载任何语言环境。 现在我们有了一个translator,它将区域设置作为“配置”,将text作为数据。由于translator是柯里化的,所以我们能够将“config”和“data”参数分开。

为什么要将“配置”和“数据”参数分开?

许多组件和函数需要使用一些功能,但不应该或不能知道“配置”部分的数据。这些组件或函数只有“数据”部分。因此,这些函数将能够在不需要了解“配置”部分的情况下使用函数。 因此,该组件或功能将更少地与系统耦合,这将使组件更具可组合性和可维护性。

我们什么时候使用柯里化

当我们知道函数中有“config”和“data”时,我们最好用柯里化。 柯里化可以让我们把它们分开。这是一个成熟系统设计的标志。因为代码质量的一大支柱是关注点分离。 即使一个函数需要所有参数才能正常运行,我们仍然更清楚何时传递参数以及在程序的哪一层上传递参数。

闭包和柯里化的关系

Cierre: es una función devuelta por una función "principal" que tiene acceso al estado interno de la función principal.
Curry: siempre conduce a cierres. Porque cada función devuelta por una función curry proporciona el estado interno de la función principal.

más ejemplos

Ahora podemos ver algunos ejemplos significativos...
Ejemplo 1️:
Dada una lista de números, incremente todos los números en 1
Entrada: [1,2,3,4,5]
Salida: [2,3,4,5,6 ]
solución:

// the curried `add` function that we defined earlier
const addOne = add(1)
const incrementNumbers = map(addOne)
const incrementedNumbers = incrementNumbers(numbers)
复制代码

Ejemplo 2️:
dada una cadena, mantenga todas las palabras que comiencen con la letra "C"
Entrada: "el curry es increíble"
Salida: "currying"
Solución:

const startsWithC = startsWith('c')
const filterStartsWithC = filter(startsWithC)
const filteredWords = filterStartsWithC(words)
复制代码

Recuerde, () => () =>. . . es otra implementación de curry, una versión más simple de curry.

En conclusión

Curry solo hace que los parámetros sean inertes. Si una función sigue devolviendo una función hasta que se satisfacen todos sus argumentos, entonces ejecuta la lógica. También vimos con ejemplos prácticos cómo puede hacer que nuestro código sea más limpio, más limpio, más componible e incluso más reutilizable. Esto aprovecha el principio de separación de preocupaciones.

Traducido de: blog.bitsrc.io/funcional-…

Supongo que te gusta

Origin juejin.im/post/7084802365508812831
Recomendado
Clasificación