是好還是壞,Mathematica提供了豐富的結構,讓你做控制的非本地傳輸,包括Return
,Catch
/Throw
,Abort
和Goto
的。但是,這種非本地控制轉移通常會與編寫健壯的程序相沖突,這些程序需要確保清理代碼(如關閉流)運行。許多語言提供了確保清理代碼在各種情況下運行的方法; Java有它的finally
塊,C++有析構函數,Common Lisp有UNWIND-PROTECT
等等。可靠的清理Mathematica中
在Mathematica中,我不知道如何完成同樣的事情。我有一個部分解決方案,看起來像這樣:
Attributes[CleanUp] = {HoldAll};
CleanUp[body_, form_] :=
Module[{return, aborted = False},
Catch[
CheckAbort[
return = body,
aborted = True];
form;
If[aborted,
Abort[],
return],
_, (form; Throw[##]) &]];
這肯定是不會贏得任何選美比賽,但也僅處理Abort
和Throw
。特別是在Return
的存在下失敗;我想如果你使用Goto
在Mathematica中做這種非本地控制,你應該得到你所得到的。
我沒有看到一個很好的解決方法。例如,沒有CheckReturn
,當你正確地做到這一點時,Return
具有非常模糊的語義。有沒有我錯過的技巧?
編輯:與Return
的問題,並在其定義中的模糊性,具有與其用條件(這在某種程度上不在數學「控制結構」)的相互作用有關。一個例子,用我的CleanUp
形式:
CleanUp[
If[2 == 2,
If[3 == 3,
Return["foo"]]];
Print["bar"],
Print["cleanup"]]
這將返回「富」不打印「清理」。同樣,
CleanUp[
baz /.
{bar :> Return["wongle"],
baz :> Return["bongle"]},
Print["cleanup"]]
將返回「bongle」而不打印清理。我沒有找到解決這個問題的方法,沒有繁瑣的,容易出錯的,也許不可能的代碼散步,或者使用Block
以某種方式在本地重新定義Return
,這很荒謬,實際上似乎並不奏效(儘管試驗它是一種好方法以完全楔入內核!)
CheckAll似乎爲這個問題提供了一個相當不錯的解決方案。在Mathematica StackExchange上查看[這個答案](http://mathematica.stackexchange.com/a/48493/142)。 – WReach 2014-05-29 03:37:30