2010-06-28 48 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]