Currying är en teknik som används inom matematik och datavetenskap och som går ut på att ändra en funktion som tar flera argument till ett antal funktioner som var och en tar ett argument. Matematikerna Moses Schönfinkel och Gottlob Frege lade grunden till denna teknik, som är uppkallad efter Haskell Brooks Curry. Currying används i Lambda-kalkylen. Vissa programmeringsspråk, som ML och Haskell, säger att funktioner endast kan ha ett argument.
Vad är currying?
Currying är en formell omvandling av en funktion f som normalt tar flera argument till en kedja av funktioner som var och en tar ett enda argument. Formellt skrivs det ofta som en omvandling från
f : X × Y → Z
till
curry(f) : X → (Y → Z).
Det betyder att i stället för att kalla f(x, y) kan man kalla curry(f)(x)(y). Resultatet blir samma, men funktionen manipuleras som en serie en-argumentsfunktioner.
Exempel
Matematisk notation:
Anta f(x, y) = x + y. Efter currying får vi g(x) = (λy. x + y). Då är g(2) en funktion som adderar 2 till sitt argument.
Haskell (språket är kurat som standard):
add :: Int -> Int -> Int add x y = x + y addTwo :: Int -> Int addTwo = add 2 -- delvis applicerad/curried; addTwo 3 = 5 JavaScript (manuell currying):
function add(x) { return function(y) { return x + y; }; } const addTwo = add(2); console.log(addTwo(3)); // 5 Partial application vs currying
Det är viktigt att skilja på currying och partial application:
- Currying är en formell omstrukturering av en funktion med flera argument till en kedja av en-argumentsfunktioner.
- Partial application är handlingen att binda några (men inte alla) argument till en funktion och få en ny funktion med färre argument. Partial application utnyttjar ofta currying, men är ett separat begrepp.
Varför använda currying?
- Ger enkel återanvändning: delvis applicerade funktioner kan återanvändas i olika sammanhang.
- Förenklar funktionell komposition och point-free-stil.
- Möjliggör högre ordningens funktioner som tar och returnerar funktioner.
- I vissa språk (t.ex. Haskell) är currying inbyggt i språkets typmodell, vilket gör funktionstyper konsekventa och enklare att kombinera.
Uncurrying (motsatsen)
Uncurrying är motsatsen till currying: att ta en kurad funktion X → (Y → Z) och omvandla den till en funktion X × Y → Z. Exempel i Haskell:
uncurry :: (a -> b -> c) -> (a, b) -> c uncurry f (x, y) = f x y Begränsningar och praktiska överväganden
- I vissa språk kan currying introducera overhead om det implementeras med många tillfälliga funktionsobjekt; kompilatorer och optimerare kan dock eliminera detta i många fall.
- Currying förändrar inte funktionens semantik, bara hur argumenten organiseras och appliceras.
- I programspråk där funktioner naturligt tar flera argument finns ofta bibliotek eller syntaktiskt stöd för att kurera och delvis applicera funktioner.
Sammanfattning
Currying är en grundläggande teknik inom funktionell programmering och formell logik som omvandlar fler-argumentsfunktioner till kedjor av en-argumentsfunktioner. Tekniken underlättar partial application, kodåteranvändning och funktionell komposition och är nära kopplad till lambda-kalkylen och typteori.