Groovy a un concept qu'il appelle «curry». Voici un exemple de leur wiki:
def divide = { a, b -> a / b }
def halver = divide.rcurry(2)
assert halver(8) == 4
Ma compréhension de ce qui se passe ici est que l'argument de droite de divide
est lié à la valeur 2. Cela ressemble à une forme d'application partielle.
Le terme currying est généralement utilisé pour désigner la transformation d'une fonction qui prend une série d'arguments en une fonction qui ne prend qu'un seul argument et renvoie une autre fonction. Par exemple, voici le type de la curry
fonction dans Haskell:
curry :: ((a, b) -> c) -> (a -> (b -> c))
Pour les personnes qui ne sont pas utilisés Haskell a
, b
et c
sont tous les paramètres génériques. curry
prend une fonction avec deux arguments et renvoie une fonction qui prend a
et retourne une fonction de b
à c
. J'ai ajouté une paire supplémentaire de supports au type pour le rendre plus clair.
Ai-je mal compris ce qui se passe dans l'exemple groovy ou s'agit-il simplement d'une application partielle mal nommée? Ou fait-il en fait les deux: c'est-à-dire se convertir divide
en fonction curry puis s'appliquer partiellement 2
à cette nouvelle fonction.
la source
Réponses:
La mise en œuvre de Groovy
curry
ne fait à aucun moment curry, même en coulisses. Elle est essentiellement identique à une application partielle.Les
curry
,rcurry
et lesncurry
méthodes renvoient unCurriedClosure
objet qui contient les arguments liés. Il a également une méthodegetUncurriedArguments
(mal nommée - vous utilisez des fonctions, pas des arguments) qui retourne la composition des arguments qui lui sont passés avec les arguments liés.Lorsqu'une fermeture est appelée, elle appelle finalement la
invokeMethod
méthode deMetaClassImpl
, qui vérifie explicitement si l'objet appelant est une instance deCurriedClosure
. Si c'est le cas, il utilise ce qui précèdegetUncurriedArguments
pour composer le tableau complet des arguments à appliquer:Sur la base de la nomenclature déroutante et quelque peu incohérente ci-dessus, je soupçonne que celui qui a écrit cela a une bonne compréhension conceptuelle, mais a peut-être été un peu précipité et, comme beaucoup de gens intelligents, a confondu le curry avec une application partielle. C'est compréhensible (voir la réponse de Paul King), même si c'est un peu malheureux; il sera difficile de corriger cela sans rompre la rétrocompatibilité.
Une solution que j'ai suggérée est de surcharger la
curry
méthode de telle sorte que quand aucun argument n'est passé, elle fasse un curry réel et déconseille d'appeler la méthode avec des arguments en faveur d'une nouvellepartial
fonction. Cela peut sembler un peu étrange , mais cela maximiserait la compatibilité descendante - car il n'y a aucune raison d'utiliser une application partielle avec zéro argument - tout en évitant la situation (IMHO) plus laide d'avoir une nouvelle fonction, différemment nommée, pour un curry approprié alors que la fonction en fait nommécurry
fait quelque chose de différent et de similaire.Il va sans dire que le résultat de l'appel
curry
est complètement différent du curry réel. Si cela fonctionnait vraiment, vous pourriez écrire:… Et ça marcherait, parce que
addCurried
ça devrait marcher comme ça{ x -> { y -> x + y } }
. Au lieu de cela, il lance une exception d'exécution et vous mourez un peu à l'intérieur.la source
and you die a little inside
Je pense qu'il est clair que le curry groovy est en fait une application partielle lorsque l'on considère des fonctions avec plus de deux arguments. considérer
sa forme curry serait
mais le curry de groovy retournera quelque chose d'équivalent à (en supposant appelé avec 1 argument x)
qui appellera f avec la valeur d'un fixe à x
c'est-à-dire que si le curry de groovy peut renvoyer des fonctions avec des arguments N-1, les fonctions curry correctement n'ont que 1 argument, donc groovy ne peut pas être curry avec curry
la source
Groovy a emprunté la dénomination de ses méthodes de curry à de nombreux autres langages FP non purs qui utilisent également une dénomination similaire pour une application partielle - peut-être malheureux pour une telle fonctionnalité centrée sur FP. Plusieurs implémentations de curry "réelles" sont proposées pour inclusion dans Groovy. Un bon fil pour commencer à lire à leur sujet est ici:
http://groovy.markmail.org/thread/c4ycxdzm3ack6xxb
La fonctionnalité existante restera sous une certaine forme et la compatibilité ascendante sera prise en considération lors d'un appel sur le nom des nouvelles méthodes, etc. - je ne peux donc pas dire à ce stade quelle sera la dénomination finale des nouvelles / anciennes méthodes. être. Probablement un compromis sur la dénomination mais nous verrons.
Pour la plupart des programmeurs OO, la distinction entre les deux termes (curry et application partielle) est sans doute largement académique; cependant, une fois que vous y êtes habitué (et que celui qui maintiendra votre code est formé pour lire ce style de codage), alors la programmation de style sans point ou tacite (qui prend en charge le "vrai" currying) permet à certains types d'algorithmes d'être exprimés de manière plus compacte. et dans certains cas plus élégamment. Il y a évidemment une certaine «beauté réside dans les yeux du spectateur», mais avoir la capacité de prendre en charge les deux styles est conforme à la nature de Groovy (OO / FP, statique / dynamique, classes / scripts, etc.).
la source
Compte tenu de cette définition trouvée chez IBM:
halver
est votre nouvelle fonction (ou fermeture) (au curry), qui ne prend désormais qu'un seul paramètre. L'appelhalver(10)
entraînerait 5.Pour cela, il transforme une fonction avec n arguments en une fonction avec n-1 arguments. La même chose est dite par votre exemple haskell ce que fait le curry.
la source
rcurry
fonction (qui prend un argument) en fonction (avec maintenant un seul argument). J'ai enchaîné la fonction curry avec un argument à ma fonction de base pour obtenir ma fonction résultante.n - 1
arguments. Voir l'exemple à la fin de ma réponse; voir également plus loin dans l'article pour en savoir plus sur la distinction qui est faite. en.wikipedia.org/wiki/…partial
.