有一种自动实现的方法。考虑以下函数:
f[a_, b_, c_] := {a, b, c}
我们希望将其隐式地“柯里化”,这样它就可以以以下任何一种方式调用:
f[1, 2, 3]
f[1, 2][3]
f[1][2][3]
如果有一种自动生成以下定义的方法(我们在下面进行),那么这就可以实现:
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]]]
如Matt在上面的答案中所述,我们可以只定义一个函数:f:=Funcion[a,Function[b,Function[c, BODY]]],但是这样我们将无法通过f[a,b,c]或f[a,b]调用f,而只能像f[a][b]或f[a][b][c]那样调用它。使用多个定义,我们可以选择不同的风格。
生成这些定义可以通过函数CurryableSetDelayed(下面定义)来完成,只需调用:
CurryableSetDelayed[f[a_, b_, c_], {a, b, c}]
即使定义了这些符号中的任何一个,它也会像SetDelayed一样正常工作。
此外,使用Notation包,您可以将其显示为赋值运算符;例如f [a_,b_,c]#={c,b,a},但我没有尝试过。
在下面的源代码中,我使用了一些临时符号,这些符号可能与会话冲突,因此如果您要使用此代码,请将其放入包名称空间中。
完整代码:
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]@@
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
更新,现在 Attributes (HoldAllComplete 等) 扩展到所有参数,因此只要在调用 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]}
Curry
:https://reference.wolfram.com/language/ref/Curry.html - gdelfinoCurry
正在逐步被CurryApplied
和OperatorApplied
取代。 - evanb