Groovy tiene un concepto que llama 'curry'. Aquí hay un ejemplo de su wiki:
def divide = { a, b -> a / b }
def halver = divide.rcurry(2)
assert halver(8) == 4
Mi comprensión de lo que está sucediendo aquí es que el argumento de la mano derecha divide
está vinculado al valor 2. Esto parece una forma de aplicación parcial.
El término curry se usa generalmente para significar transformar una función que toma una serie de argumentos en una función que solo toma un argumento y devuelve otra función. Por ejemplo, aquí está el tipo de la curry
función en Haskell:
curry :: ((a, b) -> c) -> (a -> (b -> c))
Para personas que no han usado Haskell a
, b
y c
son todos parámetros genéricos. curry
toma una función con dos argumentos y devuelve una función que toma a
y devuelve una función de b
a c
. Agregué un par adicional de corchetes al tipo para que esto sea más claro.
¿He entendido mal lo que está sucediendo en el maravilloso ejemplo o es simplemente una aplicación parcial mal nombrada? O, de hecho, hace ambas cosas: es decir, convertir divide
en una función curry y luego aplicar parcialmente 2
a esta nueva función.
fuente
Respuestas:
La implementación de Groovy en
curry
realidad no curry en ningún momento, incluso detrás de escena. Es esencialmente idéntico a la aplicación parcial.Los
curry
,rcurry
yncurry
métodos devuelven unCurriedClosure
objeto que contiene los argumentos encuadernados. También tiene un métodogetUncurriedArguments
(mal nombrado: funciones de curry, no argumentos) que devuelve la composición de los argumentos que se le pasan con los argumentos enlazados.Cuando se llama a un cierre, finalmente llama al
invokeMethod
método deMetaClassImpl
, que verifica explícitamente si el objeto que llama es una instancia deCurriedClosure
. Si es así, utiliza lo mencionado anteriormentegetUncurriedArguments
para componer el conjunto completo de argumentos a aplicar:Basado en la confusa y algo inconsistente nomenclatura anterior, sospecho que quien escribió esto tiene una buena comprensión conceptual, pero tal vez se apresuró un poco y, como muchas personas inteligentes, combinó el curry con una aplicación parcial. Esto es comprensible (ver la respuesta de Paul King), aunque un poco desafortunado; Será difícil corregir esto sin romper la compatibilidad con versiones anteriores.
Una solución que he sugerido es sobrecargar el
curry
método de tal manera que cuando no se pasan argumentos, esto realmente hace curry, y desaprobar llamar al método con argumentos a favor de una nuevapartial
función. Esto puede parecer un poco extraño , pero maximizaría la compatibilidad con versiones anteriores, ya que no hay razón para usar una aplicación parcial con cero argumentos, al tiempo que evita la situación más fea (en mi humilde opinión) de tener una nueva función con un nombre diferente para un currículum adecuado mientras la función realmente llamadocurry
hace algo diferente y confusamente similar.No hace falta decir que el resultado de llamar
curry
es completamente diferente del curry real. Si realmente curry la función, podría escribir:... y funcionaría, porque
addCurried
debería funcionar así{ x -> { y -> x + y } }
. En cambio, arroja una excepción de tiempo de ejecución y mueres un poco por dentro.fuente
and you die a little inside
Creo que está claro que el curry maravilloso es en realidad una aplicación parcial cuando se consideran funciones con más de dos argumentos. considerar
su forma de curry sería
sin embargo, el curry de groovy devolverá algo equivalente a (suponiendo que se llama con 1 argumento x)
que llamará a f con el valor de un fijo a x
es decir, si bien el curry de groovy puede devolver funciones con argumentos N-1, las funciones de curry correctamente solo tienen 1 argumento, por lo tanto, groovy no puede curry con curry
fuente
Groovy tomó prestados los nombres de sus métodos de curry de muchos otros lenguajes FP no puros que también usan nombres similares para aplicaciones parciales, tal vez desafortunados para tal funcionalidad centrada en FP. Hay varias implementaciones de curry "reales" que se proponen para su inclusión en Groovy. Un buen hilo para comenzar a leer sobre ellos está aquí:
http://groovy.markmail.org/thread/c4ycxdzm3ack6xxb
La funcionalidad existente se mantendrá de alguna forma y se tendrá en cuenta la compatibilidad con versiones anteriores al hacer una llamada sobre cómo nombrar los nuevos métodos, etc., por lo que no puedo decir en esta etapa cuál será el nombre final de los métodos nuevos / antiguos ser. Probablemente un compromiso en el nombramiento, pero ya veremos.
Para la mayoría de los programadores de OO, la distinción entre los dos términos (currículum y aplicación parcial) es discutible en gran medida académica; sin embargo, una vez que esté acostumbrado a ellos (y quien mantendrá su código está capacitado para leer este estilo de codificación), entonces la programación de estilo libre de puntos o tácita (que admite currículum "real") permite que ciertos tipos de algoritmos se expresen de manera más compacta y en algunos casos con más elegancia. Obviamente, hay algo de "belleza en los ojos del espectador" aquí, pero tener la capacidad de admitir ambos estilos está en consonancia con la naturaleza de Groovy (OO / FP, estática / dinámica, clases / scripts, etc.).
fuente
Dada esta definición encontrada en IBM:
halver
es su nueva función (currificada) (o cierre), que ahora solo necesita un parámetro. Vocaciónhalver(10)
resultaría en 5.Por lo tanto, transforma una función con n argumentos en una función con n-1 argumentos. Su ejemplo de haskell dice lo mismo que hace el curry.
fuente
rcurry
función (que toma un argumento) en una función (con ahora solo un argumento). Encadené la función curry con un argumento a mi función base para obtener mi función resultante.n - 1
argumentos. Vea el ejemplo al final de mi respuesta; También vea más adelante en el artículo para más información sobre la distinción que se está haciendo. en.wikipedia.org/wiki/…partial
.