Movatterモバイル変換


[0]ホーム

URL:


Zum Inhalt springen
WikipediaDie freie Enzyklopädie
Suche

Currying

aus Wikipedia, der freien Enzyklopädie

Currying (vor allem in der Linguistik auchSchönfinkeln) ist die Umwandlung einerFunktion mit mehreren Argumenten in eine Sequenz von Funktionen mit jeweils einem Argument. Obwohl das Verfahren 1924 vonMoses Schönfinkel[1] erfunden und vonGottlob Frege[2] um 1900 vorausgedacht wurde, wird es oft nachHaskell Brooks Curry benannt, der das Verfahren 1958 umfangreich theoretisch ausgearbeitet hat.[3]

Verfahren

[Bearbeiten |Quelltext bearbeiten]

Es sei eine Funktion gegeben, dien Argumente erfordert. Wird diese aufein Argument angewendet, so konsumiert sie nur genau dieses und liefert als Funktionswert eine weitere Funktion, die nochn1{\displaystyle n-1} Argumente verlangt. Die zurückgegebene Funktion wird anschließend auf alle weiteren Argumente angewendet.

In Typen ausgedrückt, handelt es sich um die Umrechnung einer Funktionf:A1××AnB{\displaystyle f\colon A_{1}\times \ldots \times A_{n}\to B} zu einer modifizierten Funktionfcurried:A1(A2((AnB))){\displaystyle f_{\mathrm {curried} }\colon A_{1}\to (A_{2}\to (\ldots (A_{n}\to B)\ldots ))}.[4]

Eine alternative Schreibweise istcurry(f)=fcurried{\displaystyle \operatorname {curry} (f)=f_{\mathrm {curried} }}, wobeicurry{\displaystyle \operatorname {curry} } als einOperator verstanden wird, dern{\displaystyle n}-stellige Abbildungen (fürn>1{\displaystyle n>1}) modifiziert zu einer einstelligen Abbildung, deren Bildwerte einstellige Abbildungen sind usw., wobei der Reihe nach alle Argumente der ursprünglichen Abbildung durchlaufen werden; formal:

curry:(A1××AnB)(A1(A2((AnB)))){\displaystyle \operatorname {curry} \colon (A_{1}\times \ldots \times A_{n}\to B)\,\to \,(A_{1}\to (A_{2}\to (\ldots (A_{n}\to B)\ldots )))}.

Das Konzept des Currying ist verwandt mit, aber (fürn>2{\displaystyle n>2}) verschieden von dem derpartiellen Anwendung wie etwa:

f(a1,a2,an1,):AnB,anf(a1,a2,an){\displaystyle f(a_{1},a_{2},\ldots a_{n-1},\cdot )\colon A_{n}\to B,a_{n}\mapsto f(a_{1},a_{2},\ldots a_{n})},
f(a1,,,(n1)-mal)):A2××AnB,(a2,,an)f(a1,a2,an){\displaystyle f(a_{1},\underbrace {\cdot ,\ldots ,\cdot } _{(n-1){\text{-mal}}}))\colon A_{2}\times \ldots \times A_{n}\to B,(a_{2},\dots ,a_{n})\mapsto f(a_{1},a_{2},\ldots a_{n})}.

Im einstelligen Fall (n=1{\displaystyle n=1}) hat Currying keine Auswirkung:

fcurried=f{\displaystyle f_{\mathrm {curried} }=f},

im zweistelligen Fall (n=2{\displaystyle n=2}) besteht der Zusammenhang

fcurried:A1(A2B),a1f(a1,){\displaystyle f_{\mathrm {curried} }\colon A_{1}\to (A_{2}\to B),a_{1}\mapsto f(a_{1},\cdot )}, d. h. für allea1A1{\displaystyle a_{1}\in A_{1}}:
fcurried(a1)=f(a1,){\displaystyle f_{\mathrm {curried} }(a_{1})=f(a_{1},\cdot )},

im dreistelligen Fall (n=3{\displaystyle n=3}) gilt füra1A1{\displaystyle a_{1}\in A_{1}}:

fcurried(a1):A2(A3B),a2f(a1,a2,){\displaystyle f_{\mathrm {curried} }(a_{1})\colon A_{2}\to (A_{3}\to B),a_{2}\mapsto f(a_{1},a_{2},\cdot )}, und mit zusätzlicha2A2{\displaystyle a_{2}\in A_{2}}:
fcurried(a1)(a2):A3B,a3f(a1,a2,){\displaystyle f_{\mathrm {curried} }(a_{1})(a_{2})\colon A_{3}\to B,a_{3}\mapsto f(a_{1},a_{2},\cdot )}, d. h.fcurried(a1)(a2)=f(a1,a2,){\displaystyle f_{\mathrm {curried} }(a_{1})(a_{2})=f(a_{1},a_{2},\cdot )},

allgemein:

fcurried(a1)(a2)(an)=f(a1,a2,,an){\displaystyle f_{\mathrm {curried} }(a_{1})(a_{2})\dots (a_{n})=f(a_{1},a_{2},\dots ,a_{n})},
fcurried(a1)(a2)(an1)=f(a1,a2,,an1,){\displaystyle f_{\mathrm {curried} }(a_{1})(a_{2})\dots (a_{n-1})=f(a_{1},a_{2},\dots ,a_{n-1},\cdot )}.[5]

Es kommt häufig vor, dass eine mehrstellige Abbildung nicht für alle Wertekombinationen aus den TrägermengenA1,,An{\displaystyle A_{1},\dots ,A_{n}} definiert ist, also nur auf einer Teilmenge des kartesischen ProduktsR=DfA1××An{\displaystyle R=D_{f}\subseteq A_{1}\times \cdots \times A_{n}}, d. h. auf (dem Graphen einer)Relation.[6] Man kann diese Situation behandeln, indem man entweder grundsätzlichpartielle Abbildungen zulässt und die obigen Definitionen formal übernimmt, oder man dagegen am Konzept totaler Abbildungen festhält; in letzterem Falle werden die Definitionsbereiche der beteiligten Abbildungen von der Wahl bereits festgelegter Parameter abhängig, wie das Beispiel zweistelliger Abbildungen zeigt:

fcurried(a1)=f(a1,){\displaystyle f_{\mathrm {curried} }(a_{1})=f(a_{1},\cdot )};

der Definitionsbereich dieser Abbildung ist vona1{\displaystyle a_{1}} abhängig:

{a2A2|a1A1:(a1,a2)Df}=R({a}){\displaystyle \{a_{2}\in A_{2}|\exists a_{1}\in A_{1}\colon (a_{1},a_{2})\in D_{f}\}=R^{\leftarrow }(\{a\})},

also dieUrbildfaser vona1{\displaystyle a_{1}} bezüglich des als Relation aufgefassten DefinitionsbereichsR=Df{\displaystyle R=D_{f}}.[7]

Da für n=1 giltfcurried=f{\displaystyle f_{\mathrm {curried} }=f}, kann fürfcurried{\displaystyle f_{\mathrm {curried} }} dasselbe Symbol verwendet werden wie fürf{\displaystyle f}. Man nennt diesÜberladung (siehe auchSignatur (Modelltheorie) §Anmerkungen).[8]

Beispiele

[Bearbeiten |Quelltext bearbeiten]

Lambda-Notation

[Bearbeiten |Quelltext bearbeiten]

Ein Beispiel inLambda-Notation soll das Verfahren verdeutlichen, wobei die Funktion konkret folgendermaßen definiert sei:

λx y z . x y z{\displaystyle \lambda x\ y\ z\ .\ x\ y\ z}

Die Funktion verlangt also 3 Argumente und gibt diese zurück. Die Definition ist äquivalent zu:

λx.λy.λz . x y z{\displaystyle \lambda x.\lambda y.\lambda z\ .\ x\ y\ z}

Bei der Anwendung der Funktion auf die Argumente a, b und c geschieht Folgendes:

(λx.λy.λz . x y z) a b c  Die Anwendung{\displaystyle \left(\lambda x.\lambda y.\lambda z\ .\ x\ y\ z\right)\ a\ b\ c\ {\mathsf {-\ Die\ Anwendung}}}

(λy.λz . a y z) b c{\displaystyle \left(\lambda y.\lambda z\ .\ a\ y\ z\right)\ b\ c}

(λz . a b z) c{\displaystyle \left(\lambda z\ .\ a\ b\ z\right)\ c}

a b c  Resultat{\displaystyle a\ b\ c\ {\mathsf {-\ Resultat}}}

Nach erstmaliger Anwendung der Funktion aufa,b und c wirdx im Funktionskörper durch das erste Argument a ersetzt. Das Resultat ist eine Funktion, die noch die Argumentey undz verlangt. Diese wird sofort aufb und c angewendet.

Überladung

[Bearbeiten |Quelltext bearbeiten]

Angenommen, wir haben eine zweistellige Multiplikationsfunktionmult{\displaystyle \operatorname {mult} }, die zwei natürliche Zahlen multipliziert, d. h. einem Paarnatürlicher Zahlen ihr Produkt zuordnet:

mult:{N×NN(m,n)mn{\displaystyle \operatorname {mult} \colon \,{\begin{cases}\mathbb {N} \times \mathbb {N} \to \mathbb {N} \\(m,n)\mapsto m*n\end{cases}}} mitmult(m,n)=mn{\displaystyle \operatorname {mult} (m,n)=m*n} [9]

Per Definition wird diese Funktion auf zwei natürliche Zahlen angewendet und eine natürliche Zahl wird zurückgegeben, beispielsweisemult(2,3)=6{\displaystyle \operatorname {mult} (2,3)=6}.

Wird nun zunächst das erste Argument besetzt (etwa mit2{\displaystyle 2}), das zweite noch freigelassen, entsteht eine einstellige ‚höhere Funktion‘, die selbst ein (weiteres) Argument aufnimmt und das Produkt mit diesem festen Parameter (der Nummer2{\displaystyle 2}) zurückgibt:

mult(2,):{\displaystyle \operatorname {mult} (2,\cdot )\colon \,} {NNn2n{\displaystyle {\begin{cases}\mathbb {N} \to \mathbb {N} \\n\mapsto 2*n\end{cases}}},

und für ein beliebiges festes erstes ArgumentmN{\displaystyle m\in \mathbb {N} }:

mult(m,):{\displaystyle \operatorname {mult} (m,\cdot )\colon \,} {NNnmn{\displaystyle {\begin{cases}\mathbb {N} \to \mathbb {N} \\n\mapsto m*n\end{cases}}\,} .

Currying bedeutet nun bei einer n-stelligen Funktion, diesen Vorgang so lange durchzuführen, bis nur eine noch einstellige höhere Funktion übrigbleibt. Für n = 2 ist daher:

multcurried:{N(NN)mmult(m,){\displaystyle \operatorname {mult} _{\mathrm {curried} }\colon \,{\begin{cases}\mathbb {N} \to (\mathbb {N} \to \mathbb {N} )\\m\mapsto \operatorname {mult} (m,\cdot )\end{cases}}\,} [10]

Da die Bezeichnungmult{\displaystyle \operatorname {mult} } als einstellige Funktion noch unbesetzt ist, kann diese überladen werden,[11] d. h., im einstelligen Fall wirdmult{\displaystyle \operatorname {mult} } alsmultcurried{\displaystyle \operatorname {mult} _{\mathrm {curried} }} verstanden:

mult(m)(n)=multcurried(m)(n)=mult(m,n)=mn{\displaystyle \operatorname {mult} (m)(n)=\operatorname {mult} _{\mathrm {curried} }(m)(n)=\operatorname {mult} (m,n)=m*n}.

Geometrisches Beispiel

[Bearbeiten |Quelltext bearbeiten]
f(x, y) = x^2 + x y + y^2

Man kann sich die Situation für eine Funktion mit zwei Argumentenz=f(x,y){\displaystyle z=f(x,y)}wie folgt vorstellen: das Fixieren einer Argumentvariable entspricht einerEinschränkung der zweidimensionalen Definitionsmengeauf eine eindimensionale Teilmenge, z. B.y=1{\displaystyle y=1}, die resultierende Funktion entspricht derSchnittkurve des Graphenvonf(x,y){\displaystyle f(x,y)} mit der Ebene aller Punkte(x,1,z){\displaystyle (x,1,z)}.Alle Punkte(x,y,z){\displaystyle (x,y,z)} des Graphen können somit auch durch eine zweistufige Auswahl erreicht werden:zunächst durch die Festlegung der Schnittebeney=1{\displaystyle y=1} und dann durch die Auswertung derSchnittkurves(x)=f(x,y)|y=1{\displaystyle s(x)=f(x,y)|_{y=1}} an der Stellex{\displaystyle x}.

Anwendung

[Bearbeiten |Quelltext bearbeiten]

Currying wird überwiegend in Programmiersprachen und Kalkülen verwendet, in denen Funktionen nur ein einzelnes Argument erhalten dürfen. Dazu gehören beispielsweiseML,Unlambda und derLambda-Kalkül sowie das nach Curry benannteHaskell.Viele dieser Sprachen bieten dem Programmierer allerdings syntaktische Möglichkeiten, dies zu verschleiern. Ein Beispiel hierfür ist die Äquivalenz der Funktionsdefinition im oben gezeigtenBeispiel.

JavaScript

[Bearbeiten |Quelltext bearbeiten]

Das nachfolgende Beispiel zeigt Currying inJavaScript. Zunächst wird eine Funktionuncurried_add definiert, die als Ergebnis die Summe der beiden Argumente hat. Andererseits wird eine Funktioncurried_add definiert, die eine alsClosure definierte Funktion zurückgibt, welche partiell angewendet werden kann.

functionuncurried_add(x,y){returnx+y;}functioncurried_add(x){returnfunction(y){returnx+y;};}console.log(uncurried_add(3,5));// 8console.log(curried_add(3)(5));// 8constadd_three=curried_add(3);console.log(add_three(5));// 8console.log(add_three(12));// 15

Durch Currying wird die Funktion partiell angewendet, wobei die Funktionsargumente nacheinander übergeben werden und zwischenzeitlich in einer neuen Funktion gehalten werden, die beliebig weiterverwendet werden kann.

Die Funktionen können in JavaScript mit der Lambda-Notation auch kürzer definiert werden:

constuncurried_add=(x,y)=>x+y;constcurried_add=x=>y=>x+y;

Geläufig ist in JavaScript auch das Currying durchapply, eine Methode des Prototyps von Funktionen, der ein Kontextobjekt und eine Teilmenge der Parameter übergeben werden. Das Kontextobjekt kann dabei null oder undefined sein und wird dann implizit durch das globale Objekt ersetzt:[12]

functionuncurried_add(x,y){returnx+y;}constcurried_add=uncurried_add.bind(null,3);console.log(curried_add(5));// 8

Java

[Bearbeiten |Quelltext bearbeiten]
importjava.util.function.*;classMain{staticIntBinaryOperatoruncurriedAdd=(x,y)->x+y;staticIntFunction<IntUnaryOperator>curriedAdd=x->y->x+y;publicstaticvoidmain(String[]args){System.out.println(uncurriedAdd.applyAsInt(3,5));// 8System.out.println(curriedAdd.apply(3).applyAsInt(5));// 8varaddThree=curriedAdd.apply(3);System.out.println(addThree.applyAsInt(5));// 8System.out.println(addThree.applyAsInt(12));// 15}}

Kotlin

[Bearbeiten |Quelltext bearbeiten]
valuncurried_add={x:Int,y:Int->x+y}valcurried_add={x:Int->{y:Int->x+y}}println(uncurried_add(3,5))// 8println(curried_add(3)(5))// 8valadd_three=curried_add(3)println(add_three(5))// 8println(add_three(12))// 15

C++

[Bearbeiten |Quelltext bearbeiten]

C++ führte denLambda-Kalkül mit anonymen Funktionen in die Sprache ein. Mit dem Schlüsselwortauto wird durchTypinferenz derDatentyp implizit abgeleitet, ohne den Datentypen explizit deklarieren zu müssen. Dadurch ergibt sich eine kürzere Schreibweise für die Currifizierung:

#include<iostream>usingnamespacestd;intuncurried_add(intx,inty){returnx+y;}autocurried_add(intx){return[x](inty){returnx+y;};}intmain(){cout<<uncurried_add(3,5)<<endl;// 8cout<<curried_add(3)(5)<<endl;// 8autoadd_three=curried_add(3);cout<<add_three(5)<<endl;// 8cout<<add_three(12)<<endl;// 15return0;}

Man beachte, dass die Erwähnung des Typsint im Argument des Lambda-Ausdrucks auch durchauto ersetzt werden kann, wodurch die Implementierung verallgemeinert wird. Die Parameter der benannten Funktioncurried_add kann jedoch nur durchTemplates für verschiedene Datentypen verallgemeinert werden.

C

[Bearbeiten |Quelltext bearbeiten]

Da es in der ProgrammierspracheC keine anonymen Funktionen gibt, wird eine benannte Funktionadd separat definiert, die voncurried_add zurückgegeben wird. Der Wert vonx wird in der globalen Variablenz gespeichert, da die Funktionadd nicht auf dieContinuation der Funktioncurried_add zugreifen kann.

#include<stdio.h>intuncurried_add(intx,inty){returnx+y;}intz;intadd(inty){returny+z;}typedefintfunction(int);function*curried_add(intx){z=x;returnadd;}intmain(){printf("%d\n",uncurried_add(3,5));// 8printf("%d\n",curried_add(3)(5));// 8function*add_three=curried_add(3);printf("%d\n",add_three(5));// 8printf("%d\n",add_three(12));// 15return0;}

C#

[Bearbeiten |Quelltext bearbeiten]
usingSystem;classProgram{delegateintMethod(intx,inty);delegateFunc<int,int>Curry(intx);staticMethoduncurried_add=(x,y)=>x+y;staticCurrycurried_add=x=>y=>x+y;publicstaticvoidMain(){Console.WriteLine(uncurried_add(3,5));// 8Console.WriteLine(curried_add(3)(5));// 8varadd_three=curried_add(3);Console.WriteLine(add_three(5));// 8Console.WriteLine(add_three(12));// 15}}

F#

[Bearbeiten |Quelltext bearbeiten]
letuncurried_add(x,y)=x+yletcurried_addxy=x+yprintfn"%i"(uncurried_add(3,5))// 8printfn"%i"((curried_add3)5)// 8printfn"%i"(curried_add35)// 8letadd_three=curried_add3printfn"%i"(add_three5)// 8printfn"%i"(add_three12)// 15

Go

[Bearbeiten |Quelltext bearbeiten]
packagemainimport"fmt"varuncurried_add=func(a,bint)int{returna+b}varcurried_add=func(aint)func(aint)int{returnfunc(bint)int{returna+b}}funcmain(){fmt.Println(uncurried_add(2,3))fmt.Println(curried_add(2)(3))addThree:=curried_add(3)fmt.Println(addThree(5))// 8fmt.Println(addThree(12))// 15}

Haskell

[Bearbeiten |Quelltext bearbeiten]

In der ProgrammierspracheHaskell kann eine Funktion nur genau einen Parameter haben. Wenn man eine Funktion mit mehreren Argumenten aufrufen möchte, müssen die Argumente zuerst in einem neuen Objekt zusammengesetzt werden, sodass die Funktion nur ein Argument erhält. Dafür können die Parameter in runden Klammern mit Kommata getrennt aufgelistet werden, um einTupel zu definieren.

uncurried_add(x,y)=x+y

Eine Alternative dazu ist das Currying. In der expliziten Schreibweise definiert man für jeden Wert im Tupel jeweils eine Funktion mit nur einem Argument. Solange noch nicht alle Argumente übergeben wurden, wird eine Funktion zurückgegeben, die ein Teilergebnis liefert.

curried_addx=\y->x+y

Da die Schreibweise mit mehrerenLambda-Funktionen umständlich sein kann, gibt es einesyntaktisch gezuckerte Notation, die semantisch äquivalent ist. Schreibt man die Argumente ohne runde Klammern hintereinander, erhält man automatisch eine currifizierte Funktion.

curried_addxy=x+y

Die currifizierte Funktion kann sowohl explizit als auch implizit partiell angewendet werden.

main=doprint(uncurried_add(3,5))-- 8print((curried_add3)5)-- 8print(curried_add35)-- 8letadd_three=curried_add3print(add_three5)-- 8print(add_three12)-- 15

Zudem gibt es in Haskell die Möglichkeit eine Funktion im Nachhinein zwischen currifizierter und nicht currifizierter Definition umzuwandeln. Dafür werden die Funktionencurry unduncurry verwendet.

main=doletuncurried=uncurrycurried_addprint(uncurried(3,5))-- 8letcurried=curryuncurried_addprint((curried3)5)-- 8print(curried35)-- 8letadd_three=curried3print(add_three5)-- 8print(add_three12)-- 15

Python

[Bearbeiten |Quelltext bearbeiten]
defuncurried_add(x,y):returnx+ydefcurried_add(x):returnlambday:x+yprint(uncurried_add(3,5))# 8print(curried_add(3)(5))# 8add_three=curried_add(3)print(add_three(5))# 8print(add_three(12))# 15

Raku

[Bearbeiten |Quelltext bearbeiten]
subuncurried_add($x,$y) {$x +$y }subcurried_add($x) {sub ($y) {$x +$y };}sayuncurried_add(3,5);# 8saycurried_add(3)(5);# 8my&add_three =&curried_add(3);say&add_three(5);# 8say&add_three(12);# 15

Es gibt in der ProgrammierspracheRaku die Möglichkeit, ein Funktionsobjekt erst beim Funktionsaufruf zu currifizieren.

my&uncurried_add =sub ($x,$y) {$x +$y };say&uncurried_add(3,5);# 8say&uncurried_add.assuming(3)(5);# 8my&add_three =&uncurried_add.assuming(3);say&add_three(5);# 8say&add_three(12);# 15

Ruby

[Bearbeiten |Quelltext bearbeiten]
defuncurried_add(x,y)returnx+yenddefcurried_add(x)returnlambda{|y|x+y}endputsuncurried_add(3,5)# 8putscurried_add(3).call(5)# 8add_three=curried_add(3)putsadd_three.call(5)# 8putsadd_three.call(12)# 15

Es gibt in der ProgrammierspracheRuby die Möglichkeit, ein Funktionsobjekt erst beim Funktionsaufruf zu currifizieren.

uncurried_add=lambda{|x,y|x+y}putsuncurried_add.call(3,5)# 8putsuncurried_add.curry[3][5]# 8add_three=uncurried_add.curry[3]putsadd_three.call(5)# 8putsadd_three.call(12)# 15

Scheme

[Bearbeiten |Quelltext bearbeiten]
(defineuncurried-add(lambda(xy)(+xy)))(definecurried-add(lambda(x)(lambda(y)(+xy))))(display(uncurried-add35))(newline); 8(display((curried-add3)5))(newline); 8(defineadd-three(curried-add3))(display(add-three5))(newline); 8(display(add-three12))(newline); 15

Tcl

[Bearbeiten |Quelltext bearbeiten]

InTcl ist es nicht notwendig, irgendwelche speziellen Konstrukte als curried- oder uncurried-Variante vorzubereiten.

Ein Kommando-Aufruf ist in Tcl nur eine Liste von Worten, in der das Kommando-Wort an erster Position steht. Mit dem Operator{*} kann man ein Argument, das seinerseits eine Liste ist, inplace durch deren Elemente ersetzen. Damit kann eine beim Aufruf an vorderster Position stehende Liste neben dem zu rufenden Kommando zusätzlich beliebig viele Argumente in sich tragen.

Currying ist demzufolge identisch mit dem Anhängen eines weiteren Wortes an diese Liste, und jeder mit{*} beginnende Aufruf ist ein Lambda-Call (Benannt nach den in anderen Sprachen oft „Lambda-Ausdruck“ genannten anonymen Funktionen, die sich gut auf diese Weise einbinden lassen).

Zum Addieren ist hier das Standard-Kommandotcl::mathop::+ verwendet, das zur Implementierung der hier nicht benutzten Tcl-Expression-Syntax existiert. Dieses Kommando addiert beliebig viele Argumente.

Da man solche Experimente sinnvollerweise in der Tcl-Konsole anstellt, sind hier keine expliziten print-Anweisungen nötig.

tcl::mathop::+35;# 8    direkter Aufrufsetftcl::mathop::+;#      simple "Lambda"-Liste, nur das Kommando{*}$f35;# 8    Aufruf über "Lambda" in Variable flappendf3;#      "Currying" durch Hinzufügensetf{tcl::mathop::+3};#      "Curried" alternativ direkt formuliert{*}$f5;# 8    Aufruf über "Curried Lambda"lappendf12;#      mehr Parameter hinzufügen{*}$f45;# 15 = (3+1+2) + (4+5) ... ganz natürlich

Delphi

[Bearbeiten |Quelltext bearbeiten]
programcurried;{$APPTYPE CONSOLE}{$R *.res}usesSystem.SysUtils;functionuncurried_add(a,b:Integer):Integer;beginResult:=a+b;end;functioncurried_add(a:Integer):TFunc<Integer,Integer>;beginResult:=function(b:Integer):IntegerbeginResult:=a+b;end;end;beginWriteln(uncurried_add(3,5));// 8Writeln(curried_add(3)(5));// 8varaddThree:=curried_add(3);Writeln(addThree(5));// 8Writeln(addThree(12));//15end.

Einzelnachweise und Anmerkungen

[Bearbeiten |Quelltext bearbeiten]
  1. Moses Schönfinkel:Über die Bausteine der mathematischen Logik. In:Mathematische Annalen 92 (1924). S. 305–316,Digitalisat.
  2. Gottlob Frege:Grundgesetze der Arithmetik. Hermann Pohle, Jena 1893 (Band I) 1903 (Band II)korpora.org (Memento vom 28. Oktober 2022 imInternet Archive).
  3. Haskell Brooks Curry, Robert Feys,Roger Hindley, Jonathan P. Seldin:Combinatory Logic. North Holland, 2 Bände, 1958, 1972.
  4. Dabei bezeichnet(XY){\displaystyle (X\to Y)} oder[XY]{\displaystyle [X\to Y]} die Menge der Abbildungen vonX{\displaystyle X} nachY{\displaystyle Y}.
  5. Imnullstelligen Fall (n=0) würde das Currying einer Abbildungf{\displaystyle f} ohne Parameter und mit einem WertbB{\displaystyle b\in B} eine einstellige Abbildung mit konstantem Wertb{\displaystyle b} zuordnen, also etwa
    fcurried:BB,xb{\displaystyle f_{\mathrm {curried} }\colon B\to B,x\mapsto b}.
  6. Ein Beispiel istf(a1,a2):=a1/(a1a2){\displaystyle f(a_{1},a_{2}):=a_{1}/(a_{1}-a_{2})} mita1,a2RΔR{\displaystyle a_{1},a_{2}\in \mathbb {R} \setminus \Delta _{\mathbb {R} }} (wobeiΔR{\displaystyle \Delta _{\mathbb {R} }} dieDiagonale{(a1,a2)R2|a1=a2}{\displaystyle \{(a_{1},a_{2})\in \mathbb {R} ^{2}|a_{1}=a_{2}\}} bezeichnet).
  7. Im obigen Beispiel ist diesR{a1}{\displaystyle \mathbb {R} \setminus \{a_{1}\}}.
  8. Voraussetzung ist, dass das Symbolf{\displaystyle f} nicht schon anderweitig mit Stelligkeit 1 überladen ist (siehe Beispiel unten, dies zwingt zwischenmult{\displaystyle \operatorname {mult} } undprod{\displaystyle \operatorname {prod} } zu unterscheiden).
  9. Zur Unterscheidung vom Platzhalter{\displaystyle \cdot } wird hier{\displaystyle *} als Multiplikationszeichen verwendet.
  10. Dieser Funktion könnte man auch einen eigenen Namen vergeben:
    doppelt:=multcurried(2)=mult(2,):NN{\displaystyle \operatorname {doppelt} :=\operatorname {mult} _{\mathrm {curried} }(2)=\operatorname {mult} (2,\cdot )\colon \mathbb {N} \to \mathbb {N} }
    mitdoppelt(n)=2n{\displaystyle \operatorname {doppelt} (n)=2*n}.
  11. Man unterscheide zwischenmult{\displaystyle \operatorname {mult} } und der überladenen Funktionprod{\displaystyle \operatorname {prod} } mitprod(k1,,kr)=i=1rki{\displaystyle \operatorname {prod} (k_{1},\dotsc ,k_{r})=\prod _{i=1}^{r}k_{i}} zur Stelligkeitr{\displaystyle r} und FaktorenkiN{\displaystyle k_{i}\in \mathbb {N} }. Zwar ist zweistelligmult(m,n)=prod(m,n)=mn{\displaystyle \operatorname {mult} (m,n)=\operatorname {prod} (m,n)=m*n}, aber einstellig istprod(m)=m{\displaystyle \operatorname {prod} (m)=m}, währendmult(m)=multcurried(m)=mult(m,){\displaystyle \operatorname {mult} (m)=\operatorname {mult} _{\mathrm {curried} }(m)=\operatorname {mult} (m,\cdot )} eine einstellige Funktion ist.
  12. Kyle Simpson:this & Object Prototypes. In:You Don't Know JS. 1. Auflage.Band 3. O’Reilly, 2014,ISBN 978-1-4919-0415-2,S. 26–28. 
Abgerufen von „https://de.wikipedia.org/w/index.php?title=Currying&oldid=264288623
Kategorien:

[8]ページ先頭

©2009-2026 Movatter.jp