Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/database/8.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Wolfram mathematica 讨好Mathematica_Wolfram Mathematica_Currying - Fatal编程技术网

Wolfram mathematica 讨好Mathematica

Wolfram mathematica 讨好Mathematica,wolfram-mathematica,currying,Wolfram Mathematica,Currying,可以使用此构造在Mathematica中实现有限形式的: f[a_][b_][c_] := (a^2 + b^2)/c^2 允许某人做,例如: f[4][3] /@ Range@5 {"2 + 2", "2", "8"} 我的意图是在列表中返回“8/4”和“3+5” 因此: 有没有办法将属性扩展到此构造 是否有其他方便的结构来实现这一点 除了属性之外,还有其他方法可以在Mathematica中扩展咖喱吗 我不知道有什么方法可以将属性扩展到第二个或更高版本的curried参数列表中——

可以使用此构造在Mathematica中实现有限形式的:

f[a_][b_][c_] := (a^2 + b^2)/c^2
允许某人做,例如:

f[4][3] /@ Range@5
{"2 + 2", "2", "8"} 我的意图是在列表中返回
“8/4”
“3+5”


因此:

  • 有没有办法将属性扩展到此构造

  • 是否有其他方便的结构来实现这一点

  • 除了属性之外,还有其他方法可以在Mathematica中扩展咖喱吗


我不知道有什么方法可以将属性扩展到第二个或更高版本的curried参数列表中——尽管我很想听听

您可以通过使用纯函数(尽管我不太愿意称之为“方便”)来实现与当前表达式外观相同的表达式定义:

可以使用现在未记录的符号
HeadCompose
,对当前表达式进行模式匹配:

In[65]:= MatchQ[g[x][y][z], HeadCompose[g, x_, y_, z_]]
Out[65]= True

。。。尽管这种能力对手头的事情没有帮助
HeadCompose
在几个版本之前被弃用,最终从文档中删除。但我不知道还有什么其他的方式来匹配咖喱语。我推测,它之所以被弃用,正是因为人们无法有效地将属性和定义附加到它身上,给了它一种可怕的地位:这个符号尚未完全融入长期的Mathematica系统,并且可能会发生变化。

我不认为有任何方法可以将属性应用到这样一个系统的后面部分“upvalue”模式定义

另一种方法是使用带属性的纯函数。不像模式匹配那样方便,但当您计算
f[2+2][8/4]
时,它实际上给出了Curry想要的结果。(“函数”是Mathematica的“lambda”,如果您熟悉lambda演算。)

f=Function[a,Function[b,Function[c,HoldForm@{a,b,c},HoldAll],HoldAll]

我认为您希望能够执行以下操作:

f[2+2][2/1]/@Unevaluated@{1+1,3+3}
{{2+2,2/1,1+1},{2+2,2/1,3+3}

如果你打算经常做这类事情,你可以让输入稍微容易一些:

hf[args,body]:=函数[args,body,HoldAll];设置属性[hf,HoldAll];

f=hf[a,hf[b,hf[c,HoldForm@{a,b,c}]]]

在第73-77页上,呈现了一种完全不同的咖喱方法


一般来说,如果你试图控制Mathematica计算表达式的时间,你会让自己很痛苦。在许多情况下,更好的方法是使用符号作为占位符来表示你还不想计算的表达式,然后在计算某个表达式时,你可以用所需的表达式替换符号

派对迟到-所以这不是对这个问题的直接回答(其他帖子已经很好地回答了这个问题)。我只想指出,通过使用
Stack
和异常,可以对评估进行一种非本地控制。这有点难看,但我认为还没有充分探讨。下面是一个例子:

ClearAll[f];
f := With[{stack = Stack[_]},
   With[{fcallArgs = 
      Cases[stack, HoldForm[f[x_][y_][z_]] :> Hold[x, y, z]]},
      Throw[First@fcallArgs] /; fcallArgs =!= {}]];


In[88]:= Catch[f[2+2][8/4][3+5]]

Out[88]= Hold[2+2,8/4,3+5]

这使用了这样一个事实,即头是在元素之前递归计算的。从这里您可以看到,人们能够以这种方式提取未计算的参数,并且可能可以在进一步的处理中使用它们。尽管计算被中断。还可以从
堆栈[\ux]中提取足够的信息恢复计算。我不确定是否可以在Mathematica中实现连续性,但是如果是的话,应该是沿着这些线。

有一种方法自动完成。考虑函数

f[a_, b_, c_] := {a, b, c}
我们希望将其隐式地“curryable”,因此可以通过以下任何方式调用:

f[1, 2, 3]
f[1, 2][3]
f[1][2][3]
如果有一种方法可以自动生成以下定义(我们将在下面执行此操作),则可以实现这一点:

正如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_uu,b_u,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]@@#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属性(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]}

抱歉,有一条可能不相关的评论。我刚刚搜索了“currying with Mathematica”,这个问题是Google列表中的第一个问题。虽然它已经有1年的历史了,并且已经得到了答案,但我发现给出的解决方案并不是很优雅。初始代码的简单修改如下:

ClearAll[f]
SetAttributes[f, HoldAllComplete]
f[a_, b_, c_] := {ToString@Unevaluated@a, ToString@Unevaluated@b,
ToString@Unevaluated@c}
f[a__] := Function[x, f[a, x], HoldAll]
它会产生所需的承载力:

f[2+2][2+1]/@Unevaluated@{1+1,3+3}
→ <代码>{2+2,2+1,1+1},{2+2,2+1,3+3}

它适用于三种可能的参数分区

f[1 + 1, 2 + 2, 6 + 1]
f[1 + 1, 2 + 2][6 + 1]
f[1 + 1][2 + 2][6 + 1]
并给出正确的结果:
{“1+1”、“2+2”、“6+1”}
,但在
f[1+1][2+2,6+1]
中失败。对于此版本,可以使用更高级的版本:

ClearAll[f, g]
SetAttributes[f, HoldAllComplete]
SetAttributes[g, HoldAllComplete]
f[a_, b_, c_] := (ClearAll[g]; SetAttributes[g, HoldAllComplete]; 
  Thread[Hold[{a, b, c}]] /. {Hold[e_] :> ToString@Unevaluated[e]})
f[a__] := (g[x__] := f[a, x]; g)

我相信我们可以用一个符号
f
来代替
f
f1
f2
,这似乎更合适。@W先生同意,我们可以使用
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
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]}
ClearAll[f]
SetAttributes[f, HoldAllComplete]
f[a_, b_, c_] := {ToString@Unevaluated@a, ToString@Unevaluated@b,
ToString@Unevaluated@c}
f[a__] := Function[x, f[a, x], HoldAll]
f[1 + 1, 2 + 2, 6 + 1]
f[1 + 1, 2 + 2][6 + 1]
f[1 + 1][2 + 2][6 + 1]
ClearAll[f, g]
SetAttributes[f, HoldAllComplete]
SetAttributes[g, HoldAllComplete]
f[a_, b_, c_] := (ClearAll[g]; SetAttributes[g, HoldAllComplete]; 
  Thread[Hold[{a, b, c}]] /. {Hold[e_] :> ToString@Unevaluated[e]})
f[a__] := (g[x__] := f[a, x]; g)