Wolfram mathematica 为什么';您是否持有未估价的股票?
Mathematica的计算器通常保存(或恢复?Wolfram mathematica 为什么';您是否持有未估价的股票?,wolfram-mathematica,Wolfram Mathematica,Mathematica的计算器通常保存(或恢复?HeadsUnevaluated作为Symbols参数提供的表达式: In[1]:= f[s, Unevaluated[1 + 1]] Out[2]= f[s, Unevaluated[1 + 1]] In[5]:= Trace[f[s,Unevaluated[1+1]],TraceOriginal->True] Out[5]= {f[s,Unevaluated[1+1]],{f},{s},f[s,1+1],f[s,Unevaluate
Head
sUnevaluated
作为Symbol
s参数提供的表达式:
In[1]:= f[s, Unevaluated[1 + 1]]
Out[2]= f[s, Unevaluated[1 + 1]]
In[5]:= Trace[f[s,Unevaluated[1+1]],TraceOriginal->True]
Out[5]= {f[s,Unevaluated[1+1]],{f},{s},f[s,1+1],f[s,Unevaluated[1+1]]}
但对于RuleDelayed
,情况并非如此。此外,在规则延迟
的情况下,任何数量的未评估的
包装被剥离:
In[1]:= Attributes@RuleDelayed
RuleDelayed[s, Unevaluated[1 + 1]]
RuleDelayed[s, Unevaluated@Unevaluated[1 + 1]]
RuleDelayed[s, Unevaluated@Unevaluated@Unevaluated[1 + 1]]
RuleDelayed[Unevaluated@Unevaluated@Unevaluated[1 + 1], 1 + 1]
Out[1]= {HoldRest, Protected, SequenceHold}
Out[2]= s :> 1 + 1
Out[3]= s :> 1 + 1
Out[4]= s :> 1 + 1
Out[5]= 2 :> 1 + 1
dummyFunction /; (++numberOfEvaluations; False) := Null;
In[36]:= numberOfEvaluations=0;
rd[dummyFunction,Unevaluated@Unevaluated[Unevaluated[1+1]]];
numberOfEvaluations
numberOfEvaluations=0;
RuleDelayed[dummyFunction,Unevaluated@Unevaluated[Unevaluated[1+1]]];
numberOfEvaluations
Out[38]= 4
Out[41]= 4
在规则延迟
的情况下,为什么求值器会剥离任何数量的未求值的
包装?它在哪些方面有用?是否有可能为任意符号
(f
)模拟这种行为
也不清楚为什么
跟踪
显示的规则延迟
图片比f
更复杂:
In[2]:= Trace[RuleDelayed[s,1+1],TraceOriginal->True]
Out[2]= {s:>1+1,{RuleDelayed},{s},s:>1+1,s:>1+1,{RuleDelayed},{s},s:>1+1}
它看起来像是
RuleDelayed
被计算了两次…Unevaluated
作为规则中最外层的包装出现时被剥离。这就是Unevaluated
的工作原理,即Unevaluated
不是计算任何东西的常规符号。这是一种象征。比较
In[8]:= f[s_] := g[Unevaluated[1 + 1]]
In[9]:= DownValues[f]
Out[9]= {HoldPattern[f[s_]] :> g[Unevaluated[1 + 1]]}
及
因为求值器是递归的,所以它最终足以摆脱未求值的
编辑根据Alexey的评论扩展答案:
Unevaluated
是一种惰性符号,由计算器识别并在规则内执行操作的标记。因此,Unevaluated[1+1]
保持不变,以及f[1,Unevaluated[1+1]]
。当计算RuleDelayed[s,Unevaluated[1+1]]
时,将剥离Unevaluated
,然后根据计算原则重新计算整个RuleDelayed
表达式
编辑2这是重新评估原因讨论的浓缩结果 “RuleDelayed”的实施细节导致重复评估,最终导致未评估的项目被剥离。在我回答下面的评论中,我提供了另一个命令的示例,该命令出于完全相同的原因导致双重评估。之所以会出现这种情况,是因为表达式要经过验证,一旦验证,它就会打上某个有效标志。设置有效标志将启动重新评估序列。这种情况一直持续到表达式不再更改为止。 对于其他需要验证的表达式,例如
Root
object,也会出现类似的效果:
In[41]:= Root[#1^6 + #1 - 1 & , 1]; Trace[Root[#1^6 + #1 - 1 & , 1],
TraceOriginal -> True]
Out[41]= {
HoldForm[Root[#1^6 + #1 - 1 & , 1]], {HoldForm[Root]},
{HoldForm[#1^6 + #1 - 1 & ], {HoldForm[Function]},
HoldForm[#1^6 + #1 - 1 & ]},
{HoldForm[1]},
HoldForm[Root[#1^6 + #1 - 1 & , 1]], <-- here the root had been
stamped valid, and reevaluated
HoldForm[Root[-1 + #1 + #1^6 & , 1]] <-- evaluation was trivial.
[41]中的:=Root[#1^6+#1-1&,1];跟踪[Root[#1^6+#1-1&,1],
TraceOriginal->True]
Out[41]={
HoldForm[Root[#1^6+#1-1&,1]],{HoldForm[Root]},
{HoldForm[#1^6+#1-1&],{HoldForm[Function]},
HoldForm[#1^6+#1-1&],
{HoldForm[1]},
HoldForm[Root[#1^6+#1-1&,1]],这个答案应该被认为是对@Sasha答案的补充。我相信这是一个微妙的话题,可以从多个角度进行解释
为什么这个问题非同小可
我想强调的是,所讨论的行为不是典型的,因为这不是Mathematica中大多数人的行为,也不能仅仅根据评估的一般原则来解释(特别是未评估的剥离的机制)在不使用特定行为的特定头部的实现细节的情况下(<代码> RuleDelayed < /代码>)。考虑一些普通的头,使用<代码> HorddRES/COD>属性:< /P>
In[185]:= SetAttributes[h, HoldRest];
h[1, Unevaluated[Unevaluated[Unevaluated[1 + 1]]]]
Out[186]= h[1, Unevaluated[Unevaluated[Unevaluated[1 + 1]]]]
当
In[209]:= 1:>Unevaluated@Unevaluated@Unevaluated[1+1]
Out[209]= 1:>1+1
有关剥离未估价的包装纸的一些详细信息
这是基于David Wagner的书《Mathematica中的电源编程-内核》、David Withoff的WRI技术报告《Mathematica内部结构》中的讨论,以及我自己的经验
这是一幅非常简单的求值图。Mathematica递归求值表达式,首先从“分支”(表达式)到“分支”(子表达式)和叶子(原子),然后再到“上”。在“下”的过程中,(子表达式)的头表达式被求值,然后是部分。那些头为未求值的部分不会被进一步求值(在这个意义上,求值器不会被递归调用),而未求值的部分会被剥离,并被标记为已完成。在“向上”的过程中,认为零件已经过评估。有许多步骤,包括序列拼接、与属性相关的评估,如<代码>平面代码>、<代码>无序代码>等。然后,应用当前评估的头部规则,用户定义和内置(UpValues
,DownValues
,SubValues
)。最后,这对于本次讨论很重要,对于未找到适用规则的表达式部分,将还原未计算的包装。这就是为什么对于未定义的函数f
,我们有:
In[188]:= ClearAll[f];
f[Unevaluated[1+1]]
Out[189]= f[Unevaluated[1+1]]
通过将TraceOriginal
选项设置为True
,使用TraceOriginal
,可以确认未评估的
包装已剥离,然后恢复:
In[190]:= Trace[f[Unevaluated[1+1]],TraceOriginal->True]
Out[190]= {f[Unevaluated[1+1]],{f},f[1+1],f[Unevaluated[1+1]]}
当为f
定义了一些规则时会发生什么情况?答案是每个规则应用程序都会剥离一层未评估的
In[204]:=
f[x_]:=Hold[x];
g[x_]:=f[x];
{f[Unevaluated[1+1]],g[Unevaluated[1+1]]}
{f[Unevaluated@Unevaluated[1+1]],g[Unevaluated@Unevaluated[1+1]]}
{f[Unevaluated@Unevaluated@Unevaluated[1+1]], g[Unevaluated@Unevaluated@Unevaluated[1+1]]}
Out[206]= {Hold[1+1],Hold[2]}
Out[207]= {Hold[Unevaluated[1+1]],Hold[1+1]}
Out[208]= {Hold[Unevaluated[Unevaluated[1+1]]],Hold[Unevaluated[1+1]]}
如果知道表达式particiapte的给定部分将进行多少次求值,原则上可以将该部分封装在Unevaluated
的许多层中,以防止其求值。但是,通常不可能包含此信息,并且Unevaluated
不应用作持久保持包装器-这是是Hold
的目的。但该分析可能会更清楚地表明,为了使任何数量的评估失败,进行评估的负责人必须为其定义非琐碎的规则。换句话说,通常情况下,评估过程中包括剥离一层未评估的
的部分(本身,“在表达的过程中”,诱导其重新评估-t
ClearAll[rd];
SetAttributes[rd, {HoldAllComplete, SequenceHold}];
rd[lhs_, Verbatim[Unevaluated][rhs_]] /;
Head[Unevaluated[rhs]] =!= Unevaluated := Append[rd[lhs], Unevaluated[rhs]];
rd[lhs_, Verbatim[Unevaluated][rhs_]] := rd @@ {lhs, rhs};
rd[lhs_, rhs_] /; Hold[lhs] =!= Hold[Evaluate[lhs]] := Prepend[rd[rhs], lhs];
In[173]:=
a=1;
rd[a,Unevaluated[1+1]]
rd[a,Unevaluated@Unevaluated[1+1]]
rd[a,Unevaluated@Unevaluated[1+1]]
Out[174]= rd[1,1+1]
Out[175]= rd[1,1+1]
Out[176]= rd[1,1+1]
In[183]:=
DeleteCases[Trace[rd[s,Unevaluated[1+1]],TraceOriginal->True],
x_/;!FreeQ[x,Head|Hold|Append|HoldPattern[rd[_]]]]
Out[183]= {rd[s,Unevaluated[1+1]],{rd},rd[s,Unevaluated[1+1]],
rd[s,1+1],{rd},rd[s,1+1],rd[s,1+1]}
In[184]:= Trace[RuleDelayed[s,Unevaluated[1+1]],TraceOriginal->True]
Out[184]= {s:>Unevaluated[1+1],{RuleDelayed},{s},s:>1+1,s:>1+1,{RuleDelayed},{s},s:>1+1}
ClearAll[rd];
SetAttributes[rd, {HoldRest, SequenceHold}];
Options[rd] = {"Validated" -> None};
expr : rd[args__] /; ("Validated" /. Options[Unevaluated[rd]]) =!=
Hold[expr] := (Options[
Unevaluated[rd]] = {"Validated" -> Hold[expr]}; rd[args])
In[6]:= rd[Unevaluated@Unevaluated[1 + 1],
Unevaluated@Unevaluated[Unevaluated[1 + 1]]]
Out[6]= rd[2, 1 + 1]
dummyFunction /; (++numberOfEvaluations; False) := Null;
In[36]:= numberOfEvaluations=0;
rd[dummyFunction,Unevaluated@Unevaluated[Unevaluated[1+1]]];
numberOfEvaluations
numberOfEvaluations=0;
RuleDelayed[dummyFunction,Unevaluated@Unevaluated[Unevaluated[1+1]]];
numberOfEvaluations
Out[38]= 4
Out[41]= 4
ClearAll[rd];
SetAttributes[rd, {HoldRest, SequenceHold}];
SetAttributes[returnLast, {HoldRest}]
SetAttributes[{NotValidatedQ, setValidatedFlag}, HoldAllComplete];
Options[rd] = {"Validated" -> None};
NotValidatedQ[expr_] := ("Validated" /. Options[Unevaluated[rd]]) =!=
Hold[expr];
setValidatedFlag[expr_] :=
Options[Unevaluated[rd]] = {"Validated" -> Hold[expr]};
returnLast[first_, last_] := last;
expr : rd[args__] /; NotValidatedQ[expr] :=
returnLast[setValidatedFlag[expr], rd[args]]
rdList = DeleteCases[
Trace[rd[Unevaluated@Unevaluated[1 + 1],
Unevaluated@Unevaluated[Unevaluated[1 + 1]]],
TraceOriginal ->
True], ({HoldForm[(validatedQ | setValidatedFlag)[_]], ___} |
HoldForm[_returnLast] | {HoldForm[returnLast]})] /.
rd -> RuleDelayed
RuleDelayedList =
Trace[RuleDelayed[Unevaluated@Unevaluated[1 + 1],
Unevaluated@Unevaluated[Unevaluated[1 + 1]]],
TraceOriginal -> True]
In[52]:= rdList =
Trace[rd[Unevaluated@Unevaluated[1 + 1],
Unevaluated@Unevaluated[Unevaluated[1 + 1]]], rd,
TraceOriginal -> True] /. {HoldForm[_returnLast] -> Sequence[],
rd -> RuleDelayed};
RuleDelayedList =
Trace[RuleDelayed[Unevaluated@Unevaluated[1 + 1],
Unevaluated@Unevaluated[Unevaluated[1 + 1]]], RuleDelayed,
TraceOriginal -> True];
rdList === RuleDelayedList
Out[54]= True