In der Informatik , genauer gesagt in der funktionalen Programmierung , ist Currying die Umwandlung einer Funktion mit mehreren Argumenten in eine Funktion mit einem Argument, die eine Funktion für den Rest der Argumente zurückgibt. Der umgekehrte Vorgang ist möglich und wird als Entschlüsselung bezeichnet .
Der Begriff stammt vom Namen des amerikanischen Mathematikers Haskell Curry , obwohl diese Operation zuerst von Moses Schönfinkel eingeführt wurde .
Stellen Sie sich eine Funktion vor add, die zwei Argumente ( x und y ) akzeptiert und deren Summe zurückgibt. Durch Currying erhalten wir eine Funktion addcur, die ein Argument akzeptiert und eine Funktion zurückgibt, die das zweite Argument verwendet. In Pseudosprache:
curry (add (x,y)) → addcur x → lambda (y → x + y)Das Currying ermöglicht die teilweise Anwendung, wenn sie mit Argument 3 als Curry-Funktion bezeichnet wird, und stellt eine Funktion wieder her, die ihrem Argument 3 hinzufügt.
In Haskell gibt es hier eine Funktion ohne Curry:
uncurried_add (x, y) = x + yund das gleiche nach dem Curry :
curried_add x y = x + yoder :
curried_add x = \y -> x + yDabei führt der Schrägstrich \ einen λ-Ausdruck (Lambda-Ausdruck) ein und wird zum Definieren anonymer Funktionen verwendet. Und hier ist eine Teilanwendung:
main = do print (uncurried_add (3, 5)) -- 8 print ((curried_add 3) 5) -- 8 print (curried_add 3 5) -- 8 let add_three = curried_add 3 print (add_three 5) -- 8 print (add_three 12) -- 15 BemerkungenDas Currying kann manuell oder von einem Programm durchgeführt werden. Für Funktionen mit zwei Argumenten sind hier diese Programme in Haskell:
main = do let uncurried = uncurry curried_add print (uncurried (3, 5)) -- 8 let curried = curry uncurried_add print ((curried 3) 5) -- 8 print (curried 3 5) -- 8 let add_three = curried 3 print (add_three 5) -- 8 print (add_three 12) -- 15Gleiche Funktion in Python :
def uncurried_add(x, y): return x + y def curried_add(x): return lambda y: x + y print(uncurried_add(3, 5)) # 8 print(curried_add(3)(5)) # 8 add_three = curried_add(3) print(add_three(5)) # 8 print(add_three(12)) # 15Gleiche Funktion in Caml :
let uncurried_add(x, y) = x + y;; (* Type de la fonction : (entier * entier) -> entier *) let curried_add x y = x + y;; (* Type de la fonction : entier -> entier -> entier *) uncurried_add(3,4);; (* Retourne 7. Type de la valeur retournée : entier. *) curried_add 3;; (* Retourne la fonction qui ajoute 3. Type de la valeur retournée : entier -> entier. *) (curried_add 3) 4;; (* Crée la fonction qui ajoute 3 et l'applique à l'entier 4. Retourne 7. Type de la valeur retournée : entier. *) let add_three = curried_add 3;; (* Définit la fonction add_three comme la fonction qui ajoute 3 à son argument. *) add_three 5;; (* Applique add_three à 5. Retourne 8. *) add_three 12;; (* Applique add_three à 12. Retourne 15. *)Ruby liefert den Lambda-Ausdruck mit der Curry-Methode. Die Methode verwendet als Argument ein optionales Argument: arity, das feinere Prozesse ermöglicht, auf die hier nicht eingegangen wird.
uncurried_add = lambda { |x, y| x + y } puts uncurried_add.call(3, 5) # 8 puts uncurried_add.curry[3][5] # 8 add_three = uncurried_add.curry[3] puts add_three.call(5) # 8 puts add_three.call(12) # 15Ein JAPH, der ein Beispiel für das Currying in Perl 6 ist :
sub japh (Str $lang) { say "just another $lang hacker"; } my &perl6Japh := &japh.assuming("Perl6"); perl6Japh();In C ++ 11 wurden Lambdas in die Sprache eingeführt, und in C ++ 14 wurde die Möglichkeit eingeführt, einen automatischen Rückgabetyp zu definieren , um das Schreiben bestimmter Funktionen zu vereinfachen.
Diese beiden Verbesserungen ermöglichen die Implementierung von Currying:
#include <iostream> int uncurried_add(int x, int y) { return x + y; } auto curried_add(int x) { return [x](int y) { return x + y; }; } int main() { std::cout << uncurried_add(3, 5) << std::endl; // 8 std::cout << curried_add(3)(5) << std::endl; // 8 auto add_three = curried_add(3); std::cout << add_three(5) << std::endl; // 8 std::cout << add_three(12) << std::endl; // 15 }Beachten Sie, dass seit C ++ 17 die Erwähnung des Typs int als Argument des Lambda-Ausdrucks auch durch auto ersetzt werden kann , wodurch die Implementierung verallgemeinert wird (auf Kosten der Methode curried_add zu einer impliziten Vorlage).
„ In der letzten Zeile haben wir einen Trick namens Currying (nach dem Logiker H. Curry) verwendet, um das Problem der Einführung einer binären Operation in eine Sprache zu lösen, in der alle Funktionen ein einziges Argument akzeptieren müssen. (Der Schiedsrichter bemerkt, dass "Currying" zwar schmackhafter ist, "Schönfinkeling" jedoch genauer sein könnte.) »