Avoir une fonction f qui prend les arguments x 1 , x 2 ,…, x n
- c'est à dire. f: X 1 × X 2 ×… × X n → Y
- le curry redéfinit f comme une fonction prenant un seul argument a 1 qui correspond à une autre fonction. Cette technique est utile pour une application partielle, par exemple avec une pow
fonction curry que nous pourrions écrire exp = pow(e)
.
Exemple
En supposant que nous ayons la fonction f suivante en prenant trois arguments ( f: X 1 × X 2 × X 3 → Y ):
def f(a,b,c):
return a + b * c
Le curry de cette fonction nous laisse avec f_curry: X 1 → (X 2 → (X 3 → Y)) , si nous appelions maintenant cette fonction deux fois avec f_curry(1)(2)
nous obtiendrions une fonction ( h
) équivalente à la suivante:
def h(c):
return 1 + 2 * c
La fonction curry f
pourrait être écrite comme ceci (Python 3):
def f_curry(a):
def g_curry(b):
def h(c):
return a + b * c
return h
return g_curry
Défi
Votre défi sera de curry une fonction comme décrit ci-dessus, voici les règles:
- L'entrée sera une fonction blackbox qui prend au moins 2 arguments
- La fonction d'entrée aura toujours un nombre fixe d'arguments (contrairement
printf
ou similaire, notez: vous devez prendre en charge les fonctions avec un nombre d'arguments ≥2) - Si votre langue utilise des fonctions curry par défaut (par exemple Haskell), vous pouvez vous attendre à ce que la fonction d'entrée soit définie sur N -tuples, au lieu d'une "fonction d'ordre supérieur"
- Vous pouvez prendre le nombre d'arguments en entrée
- La sortie sera l'équivalent au curry de l'entrée *
- Vous pouvez supposer que la fonction de sortie ne sera que:
- appelé avec moins ou égal au nombre d'arguments que la fonction d'entrée prend
- appelé avec des arguments du bon type
* Cela signifierait pour une entrée f
avec des N
arguments et une sortie h
que pour tous les arguments valides, a1,…,aN
elle contient cela f(a1,a2,…,aN) == h(a1)(a2)…(aN)
.
def f(a,b,c): return a + b * c
et la sortie estdef f_curry(a): def g_curry(b): def h(c): return a + b * c return h return g_curry
?f
(qui est définie quelque part) et la sortie devrait être quelque chose d'équivalentf_curry
. Ou l'entrée seraitlambda a,b,c: a+b*c
et la sortie une fonction équivalente àf_curry
.Réponses:
JavaScript (ES6), 35 octets
la source
Idris , 204 octets
Essayez-le en ligne!
Cela ressemble à un travail pour les types dépendants! Eh bien, peut-être.
C est une fonction de type curry. Étant donné un vecteur de types a = [t 1 , t 2 ,… t n ] et une fonction de type T: HVect a → Type , il renvoie un nouveau type:
Ici, HVect est le type de vecteur hétérogène du Idris Prelude - le type de n -tuples dont les éléments sont de n types différents.
c est une fonction qui prend une et T comme arguments implicites, et convertit ensuite un uncurried fonction
f
du type ((b: HVect a) → T b) dans un curry un de type C T .( C décrit simplement ce que nous souhaitons faire; c le fait réellement. Mais nous ne pouvons pas nous passer de ne pas définir C , car Idris exige que chaque définition de niveau supérieur ait une signature de type.)
Le lien TIO donne un exemple d'utilisation. Si nous définissons une fonction sur 3 tuples (Nat, Nat, String) comme suit:
uncurried [3, 4, "th"]
donne alors le même résultat quec uncurried 3 4 "th"
. Idris déduit les argumentsa=[Nat, Nat, String]
etT=const String
pour nous, je crois.J'ai basé ce code sur cet essentiel de timjb.
la source
HVect
par défaut -HVect
est essentiellement un tuple que vous pouvez annuler.Python 3 ,
5453 octetsEssayez-le en ligne!
la source
R , 96 octets
Essayez-le en ligne!
Version précédente (97 octets)
-1 octet grâce à @JayCE
la source
Noix de coco , 54 octets
Essayez-le en ligne!
Noix de coco , 40 octets
Réponse Python du port d' Erik .
Essayez-le en ligne!
la source
Python 2 , 60 octets
Essayez-le en ligne!
Le pied de page est un testeur qui utilise STDIN de la manière suivante par ligne:
[a,b,...]
)Notez que, alors qu'une liste des arguments est donnée en entrée dans le testeur, en réalité, l'équivalent au curry est ajouté à la liste et la liste est réduite par appel de fonction.
Une version similaire de 55 octets a été aimablement fournie par les ovs :
Essayez-le en ligne!
la source
Chou - fleur , 84 octets
Essayez-le en ligne!
la source
Perl 6 ,
4240 octetsEssayez-le en ligne!
-2 octets grâce à Brad Gilbert b2gills .
la source
*
, il n'est nécessaire que s'il y a quelque chose après.assuming(*,1)
.Python 2 , 78 octets
Essayez-le en ligne!
la source
Attaché , 5 octets
Essayez-le en ligne!
Simple intégré, largement inintéressant. Mais, voici une version à partir de zéro:
Attaché, 35 octets
Explication:
la source
Java 8, 46 + 318 = 364 octets
Il s'agit d'un lambda au curry (hah) prenant une fonction et un nombre d'arguments et retournant la fonction au curry.
Essayez-le en ligne
Type de soumission
Fonction d'entrée
L'entrée de fonction est un objet avec une seule méthode (à l'exclusion des méthodes héritées) représentant la fonction. Notez qu'une interface fonctionnelle standard ne peut pas être utilisée comme type d'entrée car les fonctions de (par exemple) 3 paramètres doivent être prises en charge. Notez également qu'une expression lambda convertie en un type de
java.util.function.Function
type standard peut être transmise (la méthode unique estapply
).Les exceptions vérifiées peuvent être déclarées sur la fonction d'entrée, mais elles ne peuvent pas être levées (c'est-à-dire qu'elles ne seront pas propagées à l'appelant de la fonction de sortie). Cela est présumé acceptable car les interfaces fonctionnelles de Java ne permettent pas les exceptions vérifiées (et leur propagation empêcherait la soumission de renvoyer a
Function
). Les exceptions d'exécution (attribuables àRuntimeException
ouError
) sont propagées.Fonction de sortie
Le résultat de la soumission est a
java.util.function.Function<Object, Object>
. J'ai envisagé de renvoyer une plaineObject
avec uneapply
méthode (comme dans l'entrée), mais alors une réflexion serait nécessaire pour invoquer le résultat, ce qui semblait assez gênant pour être interdit - en particulier, appeler à fond ne serait plus possible en un seul expression.Usage
Étant donné que la soumission renvoie une fonction de
Object
àObject
, la sortie peut être invoquée directement (avecapply
), mais les valeurs de retour intermédiaires suivantes doivent être converties en un type approprié (par exemplejava.util.function.Function<Object, Object>
) avant d'être invoquées. Consultez le TIO pour quelques exemples d'utilisation.Notez qu'en Java, les fonctions (c'est-à-dire les méthodes) ne sont pas des objets de première classe. Ainsi, la syntaxe utilisée dans la puce de sortie de la description du défi n'a pas de sens en Java. Plutôt que
f(a1, a2, a3)
ce que nous avonsf.apply(a1, a2, a3)
et plutôt quef(a1)(a2)(a3)
ce que nous avonsf.apply(a1).apply(a2).apply(a3)
.Limites
Lorsqu'un résultat intermédiaire est appliqué (un argument ajouté), le résultat est en fait une copie mutée du résultat d'origine. Par exemple, dans cet extrait:
la ligne 4 s'imprime
4
, mais la ligne 5 échoue, car à ce momentc2
contient déjà des arguments2
et2
(notez aussi celac2 == c
). Cela viole l'esprit du curry, mais répond aux exigences spécifiques énoncées dans le défi.Non golfé
Voir le TIO pour une copie non golfée.
la source
Julia 0,6 , 48 octets
Essayez-le en ligne!
Port de la réponse Python d'EricTheOutgolfer.
la source
APL (Dyalog Classic) ,
5857 octetsEssayez-le en ligne!
Syntaxe d'appel (avec fonction curry
g
, arguments àx1
traversx3
et nombre d'argumentsn
):((n x1 f g) x2) x3
A besoin
⎕IO←1
la source