## Wednesday, November 16, 2011

### Currying with Mathematica

Curry[f_[x__]] := f[x, ##] &
a[x_, y_, z_] := {x, y, z}
b = Curry[a[x]];
c = Curry[b[y]];

then  a[x, y, z] is the same as b[y, z] is the same as c[z].

The neat and fully automated way:

``````ClearAll[UnPattern];
ClearAll[MakeFunction]
ClearAll[CurriedDefinitions]
ClearAll[MyHold]
ClearAll[MyHold2]
ClearAll[CurryableSetDelayed]
SetAttributes[UnPattern,HoldAllComplete];
SetAttributes[MakeFunction,HoldAllComplete];
SetAttributes[CurriedDefinitions,HoldAllComplete]
SetAttributes[MyHold,HoldAllComplete]
SetAttributes[MyHold2,HoldAllComplete]
SetAttributes[CurryableSetDelayed,HoldAllComplete]
UnPattern[x_]:=Block[{pattern},MyHold[x]/. Pattern->pattern/. pattern[v_,_]:>v]
MakeFunction[param_,body_,attrs_]:=With[{p=UnPattern[param],b=UnPattern[body]},
Block[{function},MyHold[function[p,b,attrs]]/. function->Function]]
{Rest[(MyHold[fname]@@#1&)/@NestList[Drop[#1,-1]&,{args},Length[{args}]-1]],
Rest[FoldList[MakeFunction[#2,MyHold[#1],Evaluate[attrs]]&,MyHold[fname[args]],
Reverse[Drop[{args},1]]]]}]
CurryableSetDelayed[fname_[args__],body_]:={MyHold2[fname[args]:=body],
Sequence@@CurriedDefinitions[fname[args],body,Attributes[fname]]}
//. MyHold[x_]:>x/. MyHold2[x_]:>x``````

This way all you need to do is :

CurryableSetDelayed[f[a_, b_, c_], {c, b, a}]

and then you can call f in any of the following ways:
f[1, 2, 3]
``````f[1, 2][3]
f[1][2][3]``````