評估訂單

這應該儘可能明確地解釋評估順序。它可能不太適合作為 Mathematica 執行的介紹。它建立在 Mathematica 的 tutorial/Evaluation 頁面上,解釋了應用不同規則的順序,並解釋了評估引擎特別處理的功能。

評估上下文

在任何時候,程式碼都在上下文中執行。上下文由一組替換規則(其字典)和應評估它們的優先順序組成。我們將五種具有不同行為和限制的上下文分組:*設定上下文*塊上下文*匹配上下文* ReplaceAll Context * ReplaceRepeated Context

設定上下文

Set Context 是由一組 Set []操作定義的(該函式更常用於寫入 =)。主要的例子是主要執行環境。只要在不是作用域的變數上執行 Set [],就會修改其字典。Set Contexts 的其他例項來自包。包上下文與其父上下文相關,因為包中的任何模式也成為父上下文中的模式,具有適當的字首(定義 foo[x_]=3*x 變為 InnerPackageName\foo [x _] = 3 * x`)。

設定上下文只能包含具有關聯標記的規則,這是與頭部關聯的字串,可以更快地識別規則的適用性。Set[yyy_,zzz_] 的應用將通過檢查 yyy 是否為符號來確定標籤。如果是,那就是標籤。否則,它會檢查 yyy[[0]],然後檢查 yyy[[0,0]],依此類推。如果它在某個時刻被確定為符號,則將其作為標記。如果它是一個非符號原子(如 String,Integer,Real …),那麼它將丟擲一個錯誤,並且不會建立任何規則。

函式 UpSet(寫入^=)和 TagSet(寫入/: / =)(以及它們的兄弟 UpSetDelayed 和 TagSetDelayed)允許將規則與不同的 Tag 相關聯。仍然存在標籤必須是符號的限制。UpSet 會將它與表示式中的每個引數相關聯,或者如果它們是具有頭部符號的函式,則將它們與頭部相關聯。例如,在 f[a,b,c+d,e[f,g],5,h[i][j][k],p_] 上呼叫 UpSet 會將建立的規則與 abeh 相關聯。c+d5p_ 引數與它們沒有任何關聯,並將導致顯示錯誤訊息。對於每個引數,賦值仍然會成功,並且(稍後將在評估順序中明確說明)它幾乎可以用於所有目的。TagSet 就像 UpSet,但你可以為 Tag 指定一個符號。符號必須仍然可以由 Set 或 UpSet(頭部或引數中的頂級符號)設定。例如,TagSet[f, f[a,b[c]], 2] 是可以接受的,並將定義與 f 相關聯; TagSet[a, f[a,b[c]], 2]TagSet[b, f[a,b[c]], 2] 也可以接受,但是 TagSet[c, f[a,b[c]], 2] 不是。

Context 中的規則需要應用程式優先順序,因為可以有許多規則適用於給定的表示式。 (在 ReplaceAll 和 ReplaceRepeated Contexts 中也是如此,但它們的處理方式卻截然不同)。優先順序通常旨在對應於特異性的模式。給出一個表達 a[q][b[c,d],e[f,g]] 進行評估,將頭部和引數全部評估為完全(參見下面的 TODO),首先查詢標記為 b 的規則; 然後用 e 標記規則; 然後用 a 標記規則。在每組規則中,維持與給定符號相關聯的訂單。沒有空格的規則(例如 f[a,b]=3)會自動放在頂部,並按規範順序排序(排序順序)。每次新增新規則時,核心都會通過列表; 如果某些規則具有完全相同的 LHS,則它將被就地替換。否則,它進行特異性比較。如果列表中已經存在的規則 X 被確定為比新規則 Y更不具體,則 Y 緊接在 X 之前。否則,它繼續通過列表。如果沒有特定規則,則規則將放在列表的末尾。特異性檢查更復雜,並在下面的部分中更詳細地給出。

規則特異性

*如果兩個表示式沒有 BlankSequence(__),BlankNullSequence(___),Optional(:),Alternatives(|),Repeated(..),RepeatedNull(...)或可選引數(_.)的例項,那麼它們可以進行比較結構。給定兩個等價的表示式樹 X 和 Y,其中 Y 中的所有空白也是 X 中的空白,但是 X 具有空白而 Y 不具有空白,則 Y 更具體。 *如果兩個表示式是等價的,除了 _ 的某些例項已經被另一個表示式中的 __ 替換,或者 __ 已被替換為 ___,那麼前者更具體。 *如果剝離一個可選(:)或可選(_.)術語給出另一個表示式,那麼後者更具體。 *如果來自 Alternatives 的某些選擇給出了另一個表示式,那麼後者更具體。 *如果用 Repeated[foo] 替換 RepeatedNull[foo] 的所有例項,或用 foo 替換 Repeated[foo],則給出另一個表示式,然後後者更具體*這些規則的某些組合可以立即應用,但目前還不知道這是什麼情況。 *理論上,如 _List{___} 這樣的表達組合應該對它們進行相同的處理,但這種比較似乎是奇怪的依賴於上下文,偶爾會以某種方式對它們進行排序。

阻止上下文

塊上下文更具限制性,因為塊中規則的 LHS 只能是符號。也就是說,只有形式 f=2+x 的定義,而不是 f[x_]=2+x。 (注意,從實際的角度來看,函式仍然可以使用諸如`Set [Block 與其父上下文相關的定義]來構造,因為在評估 Block 期間的任何新定義都會正常轉發到包圍的上下文,但是將遮蔽一些變數集,提供可以隱藏周圍上下文的定義。在評估內部表示式時,仍然可以訪問周圍上下文中的定義。因為只能定義與符號相關的定義,所以沒有概念優先權如上。

匹配上下文

匹配規則後,存在變數的本地繫結定義。這在詞彙上發生。也就是說,它在表示式中的變數的繫結定義中排除,而不評估任何其他內容。只有在所有的替換都發生之後,它才會從頂部再次開始評估整個表示式。建立匹配上下文的主要方式是來自設定上下文或規則的規則。例如,在

g[a_]:=a+x;
f[x_]:=x+g[1];
f[x^2]
(*Yields 1+x+x^2 *)

f[x_] 規則與 f[y] 匹配後,符號 x 將繫結到值 x^2。它執行一次替換,但由於它不評估 g,它返回 x^2+g[1]。然後再次在周圍的 Set Context 中對其進行評估,併成為 1+x+x^2。匹配上下文中的評估的顯著差異在於替換不是遞迴的。當它替代 x->x^2 時,它甚至不會重複它自己的結果。

匹配上下文也由 WithModuleFunctionReplace 建立。許多其他函式在內部建立它們,例如 Plot 在評估要繪製的表示式時使用此類上下文。

ReplaceRepeated Context

ReplaceRepeated 的任何應用程式發生時,將建立 ReplaceRepeated Context。這是不同的,因為它可以具有任何表示式作為規則 LHS,包括那些沒有標籤的表示式,例如 _[_]。從這個意義上說,它是最靈活的背景。它還可以包含幾個可能衝突的規則,因此必須保持優先順序。如果適用,ReplaceRepeated Context 將首先應用列表中的第一個規則。如果它不匹配,則進入第二個,依此類推。如果規則在任何時候匹配,則返回第一個規則並再次開始。如果在任何時候發生規則應用程式並且沒有發生任何更改,它將退出 - 即使列表中稍後的其他規則將進行更改。這意味著列表中較早的任何不太具體的規則將阻止以後的規則被使用。另外,

替換所有上下文

ReplaceAll 的任何應用程式發生時,將建立 ReplaceAll Context。它的功能類似於 ReplaceRepeated 的功能,因為當兩個都可以在表示式的同一級別應用時,它的規則應用程式優先順序按順序排列。然而,它就像匹配上下文一樣,被替換的內容不會被進一步評估,甚至不被後來的規則評估 ** 。例如,x/.{x->y,y->z} 產生 y。因此,檢視 ReplaceAll 的應用程式依次應用每個規則是不正確的。相反,它遍歷樹,尋找適用的規則。當它找到匹配的東西時,它會執行替換,然後返回樹,而不遍歷新樹。值得注意的是,它試圖從上到下應用規則,結果可能不按列表的順序排列。例如,

Cos[1 + 2 Sqrt[Sin[x]]] /. {Cos[_] -> 5, Sin[_] :> (Print[1]; 10)}
Cos[1 + 2 Sqrt[Sin[x]]] /. {Sin[_] :> (Print[1]; 10), Cos[_] -> 5}

兩者都沒有列印任何東西而產生 5。因為 Cos[_] 匹配樹的更高階別,所以它首先應用該樹。

HoldEvaluate 以及執行順序

給定表示式的評估順序如下:*儘可能徹底地評估頭部*如果頭部具有 Hold 屬性(HoldFirstHoldRestHoldAllHoldAllComplete),則*檢查相關引數。除非它是 HoldAllComplete,檢查頭是否是 Evaluate。如果是,則剝去 Evaluate 並將其標記為無論如何要進行評估。 *檢查 Unevaluated 例項的引數並根據需要剝離它們,除非屬性 HoldAllComplete 存在。 *除非使用 SequenceHold,否則從 Sequences 中展平引數。 *根據情況應用 FlatListableOrderless 屬性。 *應用與引數的 upvalues 相關的評估(他們的標籤)*應用與頭部相關的評估。

當表示式的評估完成時,它被標記為完全評估。達到該表示式的後續評估不會嘗試評估它。如果在內部發生的符號上定義了新規則,則會刪除該標誌,並且可以再次對其進行評估。這個’失敗’的顯著位置是 Condition\;):條件規則可能不適用於初始評估。如果不相關的符號更改值並且現在條件適用,則表示式仍標記為完全計算,並且不會因此而更改。函式 Update 的獨特之處在於它將評估其引數,無論其已經評估過的狀態如何,都會強制進行快取重新整理

還有許多其他功能通常被視為例外,例如 HoldDeferReplacePartExtractReleaseHold。這些效果都可以通過屬性(例如 HoldAll)和普通函式定義來實現,並且不需要由評估者唯一地處理。