2010-06-28 131 views
8

上的可能的问题评估Mathematica的文档保持内的一个水平说:评估超越数学

评估仅在第一 水平的作品,直接在保持功能

为什么数学里面有这个限制吗?所以,如果我有一个以上的水平表达借此简化的例子:

控股[加[加[2,2],2]]]

现在假设我希望看到的答案是什么第二个Plus,没有评估任何低于它的级别。我已经尝试不同的东西,如:

In[290]:= Hold[Plus[Evaluate[Plus[2, 2]], 2]] 
Out[290]= Hold[Evaluate[2+2]+2] 

In[287]:= Hold[Plus[ReleaseHold[Hold[Plus[2, 2]]], 2]] 
Out[287]= Hold[ReleaseHold[Hold[2+2]]+2] 

第一保持使一切不计算在超越在这种情况下的第一级。 的目标是从最内嵌套函数到外一个使用连续保持,ReleaseHold在每个阶段,以控制表达的评价和评估函数来实现这一点。我知道我可以使用跟踪看到超越一个发生的一切都在表达但那是不同的,复杂的,有时较长表达式读取。

这似乎是唯一的办法就是提取和完全拆除的表达成使用提取物,部分或等级名单;评估我想要的表达的一部分;然后重建并重新映射每个阶段的表达式。有没有其他方法或功能可以实现我可以考虑的?

编辑:这可能是一个更好的例子来看看释放第一保持的方法。与表达:

Hold[Plus[Plus[2, Plus[2,2]], 2]]] 

如果松开第一保持并将保持在在第三再加上表达更高的水平,看起来像这样:

in = Plus[Plus[2, Hold[Plus[2,2]]], 2]]] 
out = Hold[2+2]+4 

你发现数学会当你真的想要等待时,在后台评估较低的级别。

+1

相关问题:http://stackoverflow.com/questions/1616592/hold-defer-etc – dreeves 2010-06-29 17:25:12

回答

3

我不能给出Evaluate“仅在第一级上工作,直接在一个保留函数内工作”的确切原因,但我怀疑它的部分效率,因为如果评估者必须扫描完整表达式传递给任何函数与Hold*属性嵌套Evaluate表达召开参数树,并评估它们,然后递归查找Evaluate子表达式在它刚刚进行评估,同时还能保持表达式的其余部分未计算的,尤其是当这可能并不总是无论如何都是你想要发生的事情。

否则使用ExtractReplacePart组合虽然你想要什么是很容易的:

In[51]:= expr = Hold[Plus[Plus[2, 2], 2]]; 

In[52]:= ReleaseHoldAt[expr_, partspec_] := 
    ReplacePart[expr, partspec -> Extract[expr, partspec]] 

In[53]:= ReleaseHoldAt[expr, {1, 1}] 

Out[53]= Hold[4 + 2] 

这让我们举例说明另一个原因可能没有什么意义了Evaluate在表达传递的任何级别上工作作为参数传递给用Hold*属性的函数,考虑以下表达式涉及i

In[82]:= i = 1; 

In[83]:= ReleaseHoldAt[Hold[i = 2; j = Plus[i, i]], {1, 2}] 

Out[83]= Hold[i = 2; 2] 

注意的值本来4如果我们有Plus之前评估表达式的第一部分,但结果是不同的,因为我们只是在做局部的评估,并i=2当我们评估的子表达式设置j尚未评估。有时候,这可能是你想要发生的事情,但往往很可能不是。

请记住,即使是在第一级Evaluate可以通过具有属性HoldAllComplete的功能或使用HoldComplete被击败:

In[62]:= Hold[Evaluate[Plus[2,2]]] 
Out[62]= Hold[4] 

...对比:

In[63]:= HoldComplete[Evaluate[Plus[2,2]]] 
Out[63]= HoldComplete[Evaluate[2+2]] 

最后的Trace输出可以是有点晦涩难懂,但你可以通过使用模式或感兴趣的符号,第二个参数筛选出你想要的东西:

In[88]:= Trace[Plus[Plus[Plus[1,2],3],4],Plus] 
Out[88]= {{{1+2,3},3+3,6},6+4,10} 

In[93]:= Trace[Plus[Subtract[Plus[1,2],4],8],_Plus] 
Out[93]= {{{1+2}},-1+8} 

HTH!

+0

感谢那些帮助了很多。上面的第一个功能示例简单而巧妙。它在hold的控制下从表达式中提取出想要的表达部分;现在它处于保持范围之外,因此对其进行评估,然后将其放回到从中获取的位置。我将以更长更复杂的方式尝试一些东西。 – dbjohn 2010-06-29 10:34:28

2

不涉及Extract是包装的内部零件Hold在内Hold秒,然后松开外Hold的技术:

expr=Hold[(1+2)+3]; 
[email protected][Hold,expr,{2}] 

Out[2]= Hold[3]+Hold[1+2] 

您可以在这个方向上玩各种游戏,但因为我可以不知道你想要做什么,这是有点难以具体。一些可能有用的是定义你自己的Hold不过是下坡,你想让它:

SetAttributes[DescentHold,{HoldAll}] 
DescentHold[a_Plus]:[email protected][DescentHold,Hold[a],{2}] 
DescentHold[a_]:=Hold[a] 

注意这一个接近外Hold一度内侧包裹,这样对于实例Plus踢平整度在:

DescentHold[2*3+(4+5)] 
Out[4]= Hold[4]+Hold[5]+Hold[2*3] 
3

正如你常常想在Mathematica中做一些棘手的事情时,模式匹配和规则替换来救援。然而,在这种情况下,你所要做的something weird,你必须使用Replace代替ReplaceAll(在/.运营商),这样你就可以充分利用其可选的第三个参数,给它一个级别的规范。使用你提供的例子:

In[1]:= Replace[ 
     Hold[Plus[Plus[2, 2], 2]], 
     expr_Plus :> With[{eval = expr}, eval /; True], 
     {2}] 
Out[1]= Hold[4 + 2] 

无用的前瞻性

expr_Plus :> With[{eval = expr}, eval /; True] 

规则实际上是a documented way共享的测试赛和With的结构法体之间的局部变量;在这里,你不会对局部变量做任何事情,但会以迂回的方式强制其评估 - 因为较少的迂回方式将无法工作!

编辑添加:我认为你误解了Level的结果;该表达式的{2}的两个表达式是2Plus[2, 2];您可以通过使用可选的第三个参数的水平,这确实类似于Extract可选的第三个参数的东西看到这一点:

In[2]:= Level[Hold[Plus[Plus[2, 2], 2]], {2}, Hold] 
Out[2]= Hold[2 + 2, 2] 

随着{2}级规格,Replace将尝试匹配和替换对规则这两个表达式,它将在第二个表达式上工作。

+0

@dbjohn:我希望我的编辑能够回答这个问题;如果不是,我认为这可能值得自己去考虑。 – Pillsy 2010-07-02 14:31:28

+0

我可以看到它是如何工作的第2级。不应该有相同的模式匹配第3级?哪里有一个加号头匹配和替换,或者是这个级别的加号没有“激活”的功能? – dbjohn 2010-07-02 15:48:41

+0

@dbjohn:没有。 'Plus'在3级出现的原因是'Heads - > True'设置;你会看到*符号* Plus,它是'Plus [2,2]'形式的头部,并且在级别3(就像两个2s一样),但是'expr_Plus'只会匹配头部表达式'Plus',而不是'Plus'本身! – Pillsy 2010-07-02 16:36:09

2

使用想法约ReplacePart并从answer通过Michael PilatExtract函数,一个可写HoldAndEvaluate功能,这允许他计算表达式的所希望的部分,而不需要计算其位置(它可以被标记为“MyEvaluate “)。

In[1]:= expr = Hold[MyEvaluate[2 + 2] + 2]; 

In[2]:= HoldAndEvaluate[expr_] := 
    ReplacePart[expr, 
    # -> Evaluate @@ Extract[expr, #] & /@ 
    Position[expr, MyEvaluate[_]] ]; 

In[3]:= HoldAndEvaluate[expr] 

Out[3]= Hold[4 + 2]