Eine Funktion f haben , die die Argumente x 1 , x 2 ,…, x n annimmt
- dh. f: X 1 × X 2 ×… × X n → Y
- currying definiert f als eine Funktion neu, wobei ein einzelnes Argument a 1 verwendet wird, das einer weiteren Funktion zugeordnet ist. Diese Technik ist nützlich für eine teilweise Anwendung, zum Beispiel mit einer Curry- pow
Funktion, die wir schreiben könnten exp = pow(e)
.
Beispiel
Angenommen, wir haben die folgende Funktion f mit drei Argumenten ( f: X 1 × X 2 × X 3 → Y ):
def f(a,b,c):
return a + b * c
Wenn wir diese Funktion aufrufen, erhalten wir f_curry: X 1 → (X 2 → (X 3 → Y)) . Wenn wir diese Funktion jetzt zweimal mit aufrufen f_curry(1)(2)
würden, würden wir eine function ( h
) erhalten, die dem folgenden Ergebnis entspricht:
def h(c):
return 1 + 2 * c
Die Curry-Funktion f
könnte so geschrieben werden (Python 3):
def f_curry(a):
def g_curry(b):
def h(c):
return a + b * c
return h
return g_curry
Herausforderung
Deine Herausforderung wird darin bestehen, eine Funktion wie oben beschrieben zu curry. Hier sind die Regeln:
- Die Eingabe ist eine Blackbox-Funktion, die mindestens 2 Argumente akzeptiert
- Die Eingabefunktion hat immer eine feste Anzahl von Argumenten (anders als
printf
oder ähnlich, Anmerkung: Sie müssen Funktionen mit einer beliebigen Anzahl von Argumenten ≥2 unterstützen) - Wenn Ihre Sprache standardmäßig Curry-Funktionen verwendet (z. B. Haskell), können Sie erwarten, dass die Eingabefunktion über N- Tupel definiert wird, anstatt über eine Funktion "höherer Ordnung".
- Sie können die Anzahl der Argumente als Eingabe verwenden
- Der Output ist das aktuelle Äquivalent des Inputs *
- Sie können davon ausgehen, dass die Ausgabefunktion immer nur:
- wird mit weniger oder gleich der Anzahl der Argumente aufgerufen, die die Eingabefunktion annimmt
- mit Argumenten des richtigen Typs aufgerufen
* Dies würde für eine Eingabe f
mit N
Argumenten und für eine Ausgabe bedeuten, h
dass für alle gültigen Argumente a1,…,aN
dies gilt f(a1,a2,…,aN) == h(a1)(a2)…(aN)
.
def f(a,b,c): return a + b * c
und der ausgang istdef f_curry(a): def g_curry(b): def h(c): return a + b * c return h return g_curry
?f
(die irgendwo definiert ist) und die Ausgabe sollte etwas Äquivalentes seinf_curry
. Oder die Eingabe wärelambda a,b,c: a+b*c
und die Ausgabe eine äquivalente Funktionf_curry
.Antworten:
JavaScript (ES6), 35 Byte
quelle
Idris , 204 Bytes
Probieren Sie es online!
Klingt nach einem Job für abhängige Typen! Vielleicht.
C ist eine currying Art Funktion. Bei einem Vektor der Typen a = [t 1 , t 2 ,… t n ] und einer Typfunktion T: HVect a → Type wird ein neuer Typ zurückgegeben:
Hier ist HVect der heterogene Vektortyp aus dem Idris-Präludium - der Typ von n- Tupeln, deren Elemente von n sind verschiedenen Typen sind.
c ist eine Funktion, nimmt ein und T als implizite Argumente, und dann eine wandelt uncurried Funktion
f
vom Typ ((b: HVect a) → T b) in eine curried eines vom Typ C einem T .( C beschreibt einfach, was wir tun möchten; c tut es tatsächlich. Aber wir kommen nicht damit davon, C nicht zu definieren , da Idris verlangt, dass jede Definition der obersten Ebene eine Typensignatur hat.)
Der TIO-Link enthält ein Verwendungsbeispiel. Wenn wir eine Funktion für 3-Tupel (Nat, Nat, String) wie folgt definieren:
uncurried [3, 4, "th"]
ergibt dann das gleiche Ergebnis wiec uncurried 3 4 "th"
. Idris schließt sich den Argumenten ana=[Nat, Nat, String]
undT=const String
für uns glaube ich.Ich habe diesen Code auf diesem Kern von timjb aufgebaut.
quelle
HVect
standardmäßig verwendet werden. DiesHVect
ist im Wesentlichen ein Tupel, das Sie dekomprimieren können.Python 3 ,
5453 BytesProbieren Sie es online!
quelle
R , 96 Bytes
Probieren Sie es online!
Vorherige Version (97 Bytes)
-1 Byte dank @JayCE
quelle
Kokosnuss , 54 Bytes
Probieren Sie es online!
Kokosnuss , 40 Bytes
Port of Eriks Python Antwort .
Probieren Sie es online!
quelle
Python 2 , 60 Bytes
Probieren Sie es online!
Die Fußzeile ist ein Tester, der STDIN pro Zeile folgendermaßen verwendet:
[a,b,...]
)Beachten Sie, dass, während eine Liste der Argumente als Eingabe im Tester angegeben wird, in der Realität das Curry-Äquivalent der Liste vorangestellt wird und die Liste durch Funktionsaufruf reduziert wird.
Eine ähnliche 55-Byte-Version wurde freundlicherweise von ovs bereitgestellt :
Probieren Sie es online!
quelle
Blumenkohl , 84 Bytes
Probieren Sie es online!
quelle
Perl 6 ,
4240 BytesProbieren Sie es online!
-2 Bytes dank Brad Gilbert b2gills .
quelle
*
, es ist nur notwendig, wenn etwas danach steht.assuming(*,1)
.Python 2 , 78 Bytes
Probieren Sie es online!
quelle
Attache , 5 Bytes
Probieren Sie es online!
Einfach eingebaut, weitgehend uninteressant. Aber hier ist eine Version von Grund auf neu:
Attache, 35 Bytes
Erläuterung:
quelle
Java 8, 46 + 318 = 364 Bytes
Dies ist ein Curry-Lambda (hah), das eine Funktion und eine Argumentanzahl annimmt und die Curry-Funktion zurückgibt.
Probieren Sie es online
Einreichungsart
Eingabefunktion
Die Funktionseingabe ist ein Objekt mit einer einzelnen Methode (ausgenommen geerbte Methoden), die die Funktion darstellt. Beachten Sie, dass eine Standardfunktionsschnittstelle nicht als Eingabetyp verwendet werden kann, da Funktionen von (z. B.) 3 Parametern unterstützt werden müssen. Beachten Sie auch, dass ein Lambda-Ausdruck, der in einen standardähnlichen
java.util.function.Function
Typ umgewandelt wurde, übergeben werden kann (die einzige Methode istapply
).Überprüfte Ausnahmen können in der Eingabefunktion deklariert, aber nicht ausgelöst werden (dh sie werden nicht an den Aufrufer der Ausgabefunktion weitergegeben). Dies wird als akzeptabel angesehen, da die Funktionsschnittstellen von Java keine geprüften Ausnahmen zulassen (und deren Weitergabe die Übermittlung von a verhindern würde
Function
). Laufzeitausnahmen (zuweisbar aufRuntimeException
oderError
) werden weitergegeben.Ausgangsfunktion
Die Ausgabe der Einreichung ist a
java.util.function.Function<Object, Object>
. Ich überlegte, eine EbeneObject
mit einemapply
Methode (wie in der Eingabe) zurückzugeben, aber dann wäre eine Reflektion erforderlich, um das Ergebnis aufzurufen, was unpraktisch genug schien, um nicht zulässig zu sein - insbesondere, wenn in einer einzigen Methode kein vollständiger Abwärtsaufruf mehr möglich wäre Ausdruck.Verwendung
Da die Übermittlung eine Funktion von
Object
bis zurückgibtObject
, kann die Ausgabe direkt (mitapply
) aufgerufen werden , nachfolgende Zwischenrückgabewerte müssen jedoch in einen geeigneten Typ umgewandelt werden (z. B.java.util.function.Function<Object, Object>
) umgewandelt werden. Konsultieren Sie den TIO für einige Anwendungsbeispiele.Beachten Sie, dass in Java Funktionen (dh Methoden) keine erstklassigen Objekte sind. Daher ist die im Ausgabe-Aufzählungszeichen der Challenge-Beschreibung verwendete Syntax in Java bedeutungslos. Eher als
f(a1, a2, a3)
wirf.apply(a1, a2, a3)
und eher alsf(a1)(a2)(a3)
wirf.apply(a1).apply(a2).apply(a3)
.Einschränkungen
Wenn ein Zwischenergebnis angewendet wird (ein Argument hinzugefügt), ist das Ergebnis tatsächlich eine mutierte Kopie des ursprünglichen Ergebnisses. Zum Beispiel in diesem Snippet:
Zeile 4 würde gedruckt
4
, aber Zeile 5 würde fehlschlagen, da zu diesem Zeitpunktc2
bereits Argumente2
und2
(beachte auch das) enthalten sindc2 == c
). This violates the spirit of currying, but meets the specific requirement stated in the challenge.Ungolfed
Eine unbenutzte Kopie finden Sie beim TIO.
quelle
Julia 0,6 , 48 Bytes
Probieren Sie es online!
Port von @ EricTheOutgolfers Python-Antwort.
quelle
APL (Dyalog Classic),
5857 bytesTry it online!
Calling syntax (with curried function
g
, argumentsx1
throughx3
, and number of argumentsn
):((n x1 f g) x2) x3
Requires
⎕IO←1
quelle