2011-04-14 20 views
4

考慮到我的previous question關於在大型Mathematica項目中切換數值和分析「模式」的解決方案,我想到了使用Context作爲範圍構造的想法。在Mathematica中使用上下文作爲範圍構造

其基本思想是在他們自己的上下文中進行所有數值賦值,例如,

Begin["Global`Numerical`"] 
par1 = 1; 
par2 = 2; 
... 
End[] 

並且在全局上下文中具有所有複雜的分析函數,矩陣等。

理想情況下,我將能夠在全局環境中工作,並切換到一切數字與一個簡單的Begin[Global'Numeric']和切換回End[]

不幸的是,這不起作用,因爲例如,在全局上下文中定義的f[par1_,par2_,...] := foo不會使用已在Global的子上下文中定義的par1par2等。

有沒有辦法讓子上下文從父上下文繼承定義?有沒有其他的方式來使用上下文創建一個簡單的可切換範圍?

+0

您可以隨時通過手動調整'$ ContextPath'控制範圍內,但它是一個脆弱的黑客。就我個人而言,我還沒有想出一個使用上下文進行範圍界定的好方法,但我很想看看其他人是否可以提出想法。 – 2011-04-14 19:56:00

+0

手動編輯'$ ContextPath'不一定脆弱,但你必須謹慎行事。一個好的做法是在修改它之前記住它是什麼,然後在離開「範圍」時將其設置回記憶的值。您必須小心管理「中止」和其他評估中斷。 @Leo,你應該先提出答案,因爲你先提出答案。 =) – 2011-04-14 20:09:23

+0

使用'Block'作爲'Block [{$ ContextPath = newValue},你的代碼]'會自動處理@Michael提到的許多危險(不需要明確記住舊值,不需要擔心異常和中止-S)。 – 2011-04-14 21:26:11

回答

5

好了,這裏有一個方法來解決(我認爲)是你的問題,通過適當調整$ContextPath

SetOptions[EvaluationNotebook[], CellContext -> "GlobalTestCtxt`"]; 
Remove[f, GlobalTestCtxt`Numerical`f, par1, par2]; 
f[par1_, par2_] := {par1, par2}; 

savedContextPath = $ContextPath; 
Begin["GlobalTestCtxt`Numerical`"]; 
Print[{$ContextPath, $Context}]; 
$ContextPath = DeleteCases[$ContextPath, "GlobalTestCtxt`"]; 
par1 = 1; 
par2 = 2; 
End[]; 
$ContextPath = savedContextPath; 

現在,這將分析評估:

f[par1, par2] 

而這個數字:

savedContextPath = $ContextPath; 
Begin["GlobalTestCtxt`Numerical`"]; 
$ContextPath = Prepend[$ContextPath, $Context]; 
f[par1, par2] 
End[]; 
$ContextPath = savedContextPath; 

我說它很脆弱的原因是,除非你小心,否則它很容易讓符號進入錯誤的環境。例如,假設您在評估「數值」塊之前忘記在全局範圍內評估f值。那麼,現在你的數字模塊不會工作,因爲它會變成一個(完全有效的)符號GlobalTestCtxt`Numerical`f,當你第一次評估數字模塊時,你無意中輸入了符號表。由於這樣的潛在錯誤,我個人不會使用這種方法。

編輯:修正了一個錯誤(這是必須做的數值上下文指派時隱藏「全局」上下文)

+0

+1清除示例,清除警告。 – 2011-04-14 21:51:25

+0

+1 Leo,我希望你不要介意我把'x = PrependTo [x,y]'改成'x = Prepend [x,y]'。雖然,如果你願意,你可以使用'PrependTo [x,y]'。 – Simon 2011-04-15 01:54:48

+0

是的,我明顯是指後者,謝謝。 – 2011-04-15 06:15:39