如果您評估以下代碼兩次,結果將會不同。任何人都可以解釋發生了什麼?意外陰影和`刪除[符號]`
findHull[points_] := Module[{},
Needs["ComputationalGeometry`"];
ConvexHull[points]
];
findHull[RandomReal[1, {10, 2}]];
Remove["Global`ConvexHull"];
findHull[RandomReal[1, {10, 2}]]
如果您評估以下代碼兩次,結果將會不同。任何人都可以解釋發生了什麼?意外陰影和`刪除[符號]`
findHull[points_] := Module[{},
Needs["ComputationalGeometry`"];
ConvexHull[points]
];
findHull[RandomReal[1, {10, 2}]];
Remove["Global`ConvexHull"];
findHull[RandomReal[1, {10, 2}]]
的問題是,即使模塊不評估,直到你打電話findHull
,這些符號都解決了,當你定義findHull
(即:爲findHull
新downvalue存儲在符號,而不是文本的條款)。 這意味着在第一輪中,ConvexHull
解析爲Global`ConvexHull
,因爲Needs
未被評估。 在第二輪中,ComputationalGeometry
在$ContextPath
上,所以ConvexHull
按照您的意願解決。
如果您確實無法承受預先加載ComputationalGeometry
,請參考ConvexHull
的全名:ComputationalGeometry`ConvexHull
。另請參閱this related answer。
HTH
不是問題的直接答案,但對評論太大了。作爲另一種選擇,延遲符號解析直到運行時的一般方法是使用Symbol["your-symbol-name"]
。在你的情況下,你可以在r.h.s.上替換ConvexHull
。通過Symbol["ConvexHull"]
您定義的:
findHull[points_] :=
Module[{},
Needs["ComputationalGeometry`"];
Symbol["ConvexHull"][points]];
該解決方案是不是很優雅不過,因爲Symbol["ConvexHull"]
每次都會重新執行。如果您使用$ContextPath
進行非平凡的操作,這也可能有點容易出錯。下面是修改後的版本,與自我的重新定義一個通常有用的技巧相結合,我在類似的情況下使用:
Clear[findHull];
findHull[points_] :=
Module[{},
Needs["ComputationalGeometry`"];
With[{ch = Symbol["ConvexHull"]},
findHull[pts_] := ch[pts];
findHull[points]]];
例如,
findHull[RandomReal[1, {10, 2}]]
{4, 10, 9, 1, 6, 2, 5}
什麼情況是,第一次函數被調用時,Module
的原始定義被內部替換,並且在加載所需的包並將其上下文放置在$ContextPath
後已經發生。在這裏,我們利用Mathematica用一個新定義替換舊定義的事實,如果它可以確定這些模式是相同的 - 就像在這種情況下那樣。
自我重新定義技巧有用的其他實例是,例如,一個函數調用會導致一些我們想要緩存的昂貴計算的情況,但我們不確定該函數是否會被調用。然後,這樣的構造允許在第一次調用函數時自動緩存計算出的(比如符號)結果。
謝謝,有道理。我發現另一個上下文gotcha是函數內定義的函數包內的MyPackage被放入私人'而不是MyPackage'Private' – 2011-02-14 05:30:37
@Yaroslav。無法重現那一個 - 你記得使用Begin [「` Private `」]而不是Begin [「Private`」](因爲如果你沒有,那會導致你描述的行爲)? – Janus 2011-02-14 05:57:50