There is a way to do it automatically. Consider the function
f[a_, b_, c_] := {a, b, c}
for which we want to make it implicitly "curryable", so it could be called in any of these ways:
f[1, 2, 3]
f[1, 2][3]
f[1][2][3]
This could be achieved if there is a way to generate the following definitions automatically (which we do below):
f[a_, b_, c_] := {a, b, c}
f[a_, b_] := Function[c, f[a, b, c]]
f[a_] := Function[b, Function[c, f[a, b, c]]]
As in the other answer above by Matt, we could have done only one definition: f:=Funcion[a,Function[b,Function[c, BODY]]], but then we will not be able to call f via f[a,b,c] or f[a,b], and will have to call it only as f[a][b] or f[a][b][c]. With multiple definitions we can choose either styles.
Generating these definitions could be done by the function (defined below) CurryableSetDelayed, simply by calling:
CurryableSetDelayed[f[a_, b_, c_], {a, b, c}]
This will work as expected even if any of these symbols is defined, just like SetDelayed would work.
Also, with Notation package you could make it appear as an assignment operator; say f[a_,b_,c]#={c,b,a}, but I didn't try it.
In the source below I use some ad hoc symbols which may conflict with the session, so if you are going to use this, enclose it in a package namespace.
The full code:
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]]
CurriedDefinitions[fname_[args__],body_,attrs_]:=MapThread[MyHold2[#1:=#2]&,
{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
Update, now Attributes (HoldAllComplete,etc.) extends to all parameters, so the following works as expected, as long as you set the attributes before calling CurryableSetDelayed:
In[1185]:= ClearAll[f];
SetAttributes[f, {HoldAllComplete}]
CurryableSetDelayed[
f[a_, b_, c_], {ToString@Unevaluated@a, ToString@Unevaluated@b,
Unevaluated@c, Hold@c}];
f[1 + 1, 2 + 2, c + 1]
f[1 + 1, 2 + 2][c + 1]
f[1 + 1][2 + 2][c + 1]
Out[1188]= {"1 + 1", "2 + 2", Unevaluated[c + 1], Hold[c + 1]}
Out[1189]= {"1 + 1", "2 + 2", Unevaluated[c + 1], Hold[c + 1]}
Out[1190]= {"1 + 1", "2 + 2", Unevaluated[c + 1], Hold[c + 1]}