關於對性能的影響(因爲你的第一個問題已經被回答) - 通過各種手段,做檢查,但是在你的頂層函數中(它直接從用戶的功能接收數據,用戶也可以是另一個獨立的模塊,由你或其他人編寫)。不要把這些檢查放在你所有的中間函數中,因爲這些檢查將會重複,而且確實是不合理的。
EDIT
爲了解決中間函數,通過@Nasser評價引發的錯誤的問題:有一個很簡單的技術,該技術允許一個上切換圖案的檢查和關斷「點擊」。您可以將模式存儲在包中的變量中,這些變量在函數定義之前定義。
下面是一個示例,其中f
是頂級函數,而g
和h
是「內部函數」。我們定義兩種模式:主功能和內部的,就像這樣:
Clear[nlPatt,innerNLPatt ];
nlPatt= _?(!VectorQ[#,NumericQ]&);
innerNLPatt = nlPatt;
現在,我們定義功能:
ClearAll[f,g,h];
f[vector:nlPatt]:=g[vector]+h[vector];
g[nv:innerNLPatt ]:=nv^2;
h[nv:innerNLPatt ]:=nv^3;
注意的是,圖案內取代的定義定義時間,而不是運行時間,所以這與手動編碼這些模式完全相同。一旦你考,你只需要改變一個行:從
innerNLPatt = nlPatt
到
innerNLPatt = _
並重新加載你的包。
最後一個問題是 - 你如何快速找到錯誤?我回答了here,在部分中,「使用Throw可以拋出異常,而不是返回$Failed
。」和「元編程和自動化」。
編輯完
我包括這個問題在我的書here一個簡短的討論。在這個例子中,運行時間增加了10%,這是IMO可接受的邊界。在這種情況下,檢查更簡單,性能損失更小。通常,對於任何計算密集型的函數,正確編寫的類型檢查僅佔總運行時間的一小部分。
一些技巧,這是很好的瞭解:
- 模式匹配器可以非常快,語法使用時(無
Condition
或PatternTest
存在的模式)。
例如:
randomString[]:[email protected][{97,122},5];
rstest = Table[randomString[],{1000000}];
In[102]:= MatchQ[rstest,{__String}]//Timing
Out[102]= {0.047,True}
In[103]:= MatchQ[rstest,{__?StringQ}]//Timing
Out[103]= {0.234,True}
僅僅因爲在後者的情況下使用了PatternTest
,檢查要慢得多,因爲評價者由圖案匹配每個元素調用,而在第一情況下,一切都是純粹的語法,所有都是在模式匹配器內完成的。
- 同樣是真實爲解壓數值列表(定時差是相似的)。然而,對於包裝的數字列表,
MatchQ
和其他模式測試功能不解開某些特殊模式,此外,其中一些檢查是瞬間。
下面是一個例子:
In[113]:=
test = RandomInteger[100000,1000000];
In[114]:= MatchQ[test,{__?IntegerQ}]//Timing
Out[114]= {0.203,True}
In[115]:= MatchQ[test,{__Integer}]//Timing
Out[115]= {0.,True}
In[116]:= Do[MatchQ[test,{__Integer}],{1000}]//Timing
Out[116]= {0.,Null}
相同,顯然,似乎對於功能是真實的像VectorQ
,MatrixQ
和ArrayQ
與某些謂詞(NumericQ
) - 這些測試是非常有效的。
- 在很大程度上取決於你如何寫你的測試,即你重用何種程度上有效的數學結構。
例如,我們要測試的,我們有一個真正的數字矩陣:
In[143]:= rm = RandomInteger[10000,{1500,1500}];
這裏是最直接的和緩慢的方式:
In[144]:= MatrixQ[rm,NumericQ[#]&&Im[#]==0&]//Timing
Out[144]= {4.125,True}
這是更好的,因爲我們更好地重用了模式匹配器:
In[145]:= MatrixQ[rm,NumericQ]&&FreeQ[rm,Complex]//Timing
Out[145]= {0.204,True}
我們沒有然而利用矩陣的包裝性質。這還是更好的:
In[146]:= MatrixQ[rm,NumericQ]&&Total[Abs[Flatten[Im[rm]]]]==0//Timing
Out[146]= {0.047,True}
但是,這不是結束。下面一個是接近瞬間:
In[147]:= MatrixQ[rm,NumericQ]&&Re[rm]==rm//Timing
Out[147]= {0.,True}
我有時也發現自己想知道的這對性能的影響,* + 1 *對於這個問題 – Szabolcs 2012-01-09 09:57:59
我應該做的性能問題的部分作爲一個單獨的問題或只是離開這裏? – Nasser 2012-01-09 10:00:26
我會把它留在這裏。我突出強調了他們,因爲我認爲閱讀和*注意*這種方式更容易。否則許多人將永遠不會閱讀那麼遠。如果你不接受我的回答,這個問題會吸引更多的意見。 – Szabolcs 2012-01-09 10:01:48