Wolfram mathematica 关于条件(/;)的问题
Wolfram mathematica 关于条件(/;)的问题,wolfram-mathematica,Wolfram Mathematica,Condition具有属性HoldAll,该属性阻止在应用条件之前计算其第一个参数。但是由于某种原因,条件会计算其第一个参数,即使测试给出了False: In[1]:= Condition[Print[x],False] During evaluation of In[1]:= x Out[1]= Null/;False 为什么会这样?如果测试给出False,条件会评估其第一个参数,出于什么目的?在哪些情况下,此行为可能有用 p.S.条件用作设置延迟的第二个参数时,其行为不同: In[5]:=
Condition
具有属性HoldAll
,该属性阻止在应用条件之前计算其第一个参数。但是由于某种原因,条件
会计算其第一个参数,即使测试给出了False
:
In[1]:= Condition[Print[x],False]
During evaluation of In[1]:= x
Out[1]= Null/;False
为什么会这样?如果测试给出False
,条件会评估其第一个参数,出于什么目的?在哪些情况下,此行为可能有用
p.S.条件
用作设置延迟
的第二个参数时,其行为不同:
In[5]:= f:=Condition[Print[x],False]; f
Out[6]= f
In[31]:= RuleCondition[$ConditionHold[$ConditionHold[Print[3.`]]],True]
Out[31]= $ConditionHold[$ConditionHold[Print[3.]]]
In[32]:= RuleCondition[$ConditionHold[$ConditionHold[Print[3.`]]],False]
Out[32]= Fail
这是我对所有案例的预期 条件
使用通常取决于左手边的内容,因此它必须至少在某种程度上评估LHS。考虑:
MatchQ[3, a_ /; IntegerQ[a]]
真的
p={a,b};
MatchQ[{3,0.2},p/;IntegerQ[a]&b<1]
真的
无论是从这个还是从这个角度,我都会猜到Condition
具有属性HoldRest
,而不是HoldAll
。它可能需要HoldAll
进行一些内部使用,可能与SetDelayed
的用法有关。据我所知(其他回答者已经提到了这一点),Condition
不应被视为一个独立的函数,而应被视为一个用于形成涉及模式的更大表达式的包装器。但我想强调的是,这里的微妙之处部分来自这样一个事实:Rule
和RuleDelayed
都是范围界定结构。一般来说,作用域构造必须有一个变量绑定阶段,在该阶段,它们解决变量名称中可能存在的冲突,并实际将变量绑定到作用域构造体(或者,在规则
和规则延迟
的规则的r.h.s.)中出现的变量。这可能被认为是作用域结构内部工作的一部分,但是,由于Mathematica允许通过属性和Evaluate
之类的东西进行顶级操作,作用域结构并不像看上去的那样是黑盒子-我们可以通过强制变量声明或主体,或两者来更改绑定,在绑定发生之前进行计算-例如,通过删除一些Hold*
-属性。我更详细地讨论了这些事情,尽管我不知道作用域构造的确切实现细节,我不得不猜测
返回到规则
、规则延迟
和条件
的情况,对跟踪
所讨论的示例之一有指导意义:
In[28]:= Trace[Cases[{3,3.},a_:>Print[a]/;(Print["!"];IntegerQ[a])],RuleCondition,TraceAbove->All]
During evaluation of In[28]:= !
During evaluation of In[28]:= !
During evaluation of In[28]:= 3
Out[28]= {Cases[{3,3.},a_:>Print[a]/;(Print[!];IntegerQ[a])],
{RuleCondition[$ConditionHold[$ConditionHold[Print[3]]],True],
$ConditionHold[$ConditionHold[Print[3]]]},
{RuleCondition[$ConditionHold[$ConditionHold[Print[3.]]],False],Fail},
{Print[3]},{Null}}
您看到的是,当条件
与规则
或规则延迟
一起使用时,会出现特殊的内部标题RuleCondition
。我的猜测是,这些实现了将模式变量的条件包括在内的机制,包括变量绑定。将条件
用作独立函数时,不会显示这些条件。这些头对于条件机制的真正工作至关重要。
您可以查看它们在规则
和规则延迟
中的工作方式:
In[5]:= f:=Condition[Print[x],False]; f
Out[6]= f
In[31]:= RuleCondition[$ConditionHold[$ConditionHold[Print[3.`]]],True]
Out[31]= $ConditionHold[$ConditionHold[Print[3.]]]
In[32]:= RuleCondition[$ConditionHold[$ConditionHold[Print[3.`]]],False]
Out[32]= Fail
您可以看到,例如,案例
只拾取表单$ConditionHold[$ConditionHold[something]]]
的元素,而忽略那些规则条件
导致失败的元素。现在,当您使用条件
作为独立函数时,会发生什么情况?因此结果会有所不同
我知道的一个很好的例子,很好地说明了上述几点,是在中,其中讨论了使用
的
版本的可能实现,该版本按顺序绑定。我将在这里重复这一讨论的一部分,因为它很有启发性。我们的想法是制作一个版本的With,其中以前的声明可以用于声明列表的下一个声明。如果我们称之为Let
,那么,例如
Clear[h, xl, yl];
xl = 1;
yl = 2;
h[x_, y_] := Let[{xl = x, yl = y + xl + 1}, xl^2 + yl^2];
h[a, b]
我们应该
a^2+(1+a+b)^2
其中一个建议的实施方案是:
ClearAll[Let];
SetAttributes[Let, HoldAll];
Let /: (lhs_ := Let[vars_, expr_ /; cond_]) :=
Let[vars, lhs := expr /; cond]
Let[{}, expr_] := expr;
Let[{head_}, expr_] := With[{head}, expr]
Let[{head_, tail__}, expr_] := With[{head}, Let[{tail}, expr]]
(这是因为巴斯蒂安·埃尔德努斯)。这里发生的事情是,这个Let
在运行时执行绑定,而不是在定义函数时执行绑定。一旦我们想要使用共享局部变量,它就会失败:
Clear[f];
f[x_,y_]:=Let[{xl=x,yl=y+xl+1},xl^2+yl^2/;(xl+yl<15)];
f[x_,y_]:=x+y;
?f
Global`f
f[x_,y_]:=x+y
如果您跟踪最后一次执行,就不清楚为什么条件
没有在这里触发。原因是我们把装订阶段搞砸了。这是我的改进版,没有这些缺陷:
ClearAll[LetL];
SetAttributes[LetL, HoldAll];
LetL /: Verbatim[SetDelayed][lhs_, rhs : HoldPattern[LetL[{__}, _]]] :=
Block[{With}, Attributes[With] = {HoldAll};
lhs := Evaluate[rhs]];
LetL[{}, expr_] := expr;
LetL[{head_}, expr_] := With[{head}, expr];
LetL[{head_, tail__}, expr_] :=
Block[{With}, Attributes[With] = {HoldAll};
With[{head}, Evaluate[LetL[{tail}, expr]]]];
is所做的是在定义时而不是运行时将LetL
扩展为嵌套的,这发生在绑定阶段之前。现在,让我们看看:
In[122]:=
Clear[ff];
ff[x_,y_]:=LetL[{xl=x,yl=y+xl+1},xl^2+yl^2/;(xl+yl<15)];
Trace[ff[3,4]]
Out[124]= {ff[3,4],
{With[{xl$=3},With[{yl$=4+xl$+1},RuleCondition[$ConditionHold[$ConditionHold[xl$^2+yl$^2]],
xl$+yl$<15]]],With[{yl$=4+3+1},RuleCondition[$ConditionHold[$ConditionHold[3^2+yl$^2]],3+yl$<15]],
{4+3+1,8},RuleCondition[$ConditionHold[$ConditionHold[3^2+8^2]],3+8<15],
{{3+8,11},11<15,True},RuleCondition[$ConditionHold[$ConditionHold[3^2+8^2]],True],
$ConditionHold[$ConditionHold[3^2+8^2]]},3^2+8^2,{3^2,9},{8^2,64},9+64,73}
您可以看到,LetL
在定义时已扩展,如广告所示。由于模式变量绑定发生在这之后,所以一切正常。此外,如果我们添加另一个定义:
ff[x_,y_]:=x+y;
?ff
Global`ff
ff[x_,y_]:=With[{xl=x},With[{yl=y+xl+1},xl^2+yl^2/;xl+yl<15]]
ff[x_,y_]:=x+y
ff[x_u,y_u]:=x+y;
?ff
全球`ff
ff[x_u,y_u]:=With[{xl=x},With[{yl=y+xl+1},xl^2+yl^2/;xl+ylWith attributeHoldRest
cases[{3,3},a:>Print[a]/;IntegerQ[a]]
@Alexey,是不是因为规则延迟了而不是条件
的Hold属性而导致了案例
的例子
呢?我认为“把戏”可能会落在对/;
的特殊处理中:=
你所说明的。@Mr Wizard你是对的。取消保护[Condition];ClearAttributes[Condition,HoldAll];Cases[{3,3},a:>Print[a]/;IntegerQ[a]]
不会改变上述行为。似乎当条件
置于RuleDelayed
和SetDelayed
的第二个参数内时,可能TagSetDelayed
和UpSetDelayed
的工作方式与默认情况下完全不同。有趣的是RuleDelayed
它的工作原理不同
In[122]:=
Clear[ff];
ff[x_,y_]:=LetL[{xl=x,yl=y+xl+1},xl^2+yl^2/;(xl+yl<15)];
Trace[ff[3,4]]
Out[124]= {ff[3,4],
{With[{xl$=3},With[{yl$=4+xl$+1},RuleCondition[$ConditionHold[$ConditionHold[xl$^2+yl$^2]],
xl$+yl$<15]]],With[{yl$=4+3+1},RuleCondition[$ConditionHold[$ConditionHold[3^2+yl$^2]],3+yl$<15]],
{4+3+1,8},RuleCondition[$ConditionHold[$ConditionHold[3^2+8^2]],3+8<15],
{{3+8,11},11<15,True},RuleCondition[$ConditionHold[$ConditionHold[3^2+8^2]],True],
$ConditionHold[$ConditionHold[3^2+8^2]]},3^2+8^2,{3^2,9},{8^2,64},9+64,73}
?ff
Global`ff
ff[x_,y_]:=With[{xl=x},With[{yl=y+xl+1},xl^2+yl^2/;xl+yl<15]]
ff[x_,y_]:=x+y;
?ff
Global`ff
ff[x_,y_]:=With[{xl=x},With[{yl=y+xl+1},xl^2+yl^2/;xl+yl<15]]
ff[x_,y_]:=x+y