2011-11-27 67 views
7

你可以模式匹配對函數的多個參數創建一個元組,然後在比賽中表現解構它:在OCaml中,匹配函數的多個參數的規範方法是什麼?

let f x y = 
    match x, y with 
    | pattern1 -> expr1 
    | ... 

另外,如果你不需要咖喱功能,你可以通過做使f需要一個元組作爲唯一的參數:

let f (x, y) = function 
    | pattern1 -> expr1 
    | ... 

後一種方法的優點是,你不必在每次定義一個函數時寫的參數兩次。但是採用元組的函數似乎不像咖喱類那樣受歡迎。

那麼哪兩個在OCaml社區被視爲規範或首選?

編輯:正如墊指出下面,我的意思是let f = function blah blah在第二個代碼段。

回答

8

元組不僅僅是一個語法結構,它代表了一個真正的數據結構。這意味着在xy尚未被元組化的情況下,fun (x,y)(非常輕微)效率低於f x y,因爲元組必須被分配。如果這是不明確的,相當於在Java中是

void foo(X x, Y y) { ... } 
void bar(Tuple<X,Y> t) { ... } 

/* client code */ 
X x = new X(); 
Y y = new Y(); 

foo(x, y); // Just uses x and y directly 
bar(new Tuple<X,Y>(x, y)); // Has to "new" a Tuple 

出於這個原因,這是一般最好避免使用元組作爲函數的參數,除非你有一個很好的理由這樣做。

P.S.類似的考慮適用於數據類型聲明,其中以下是微妙的不同:

type 'a foo = Foo of 'a * 'a; 
type 'a bar = Bar of ('a * 'a); 

Foo是一種數據類型構造函數有兩個參數。 Bar是一個構造函數,它接受一個參數(一個元組)。

4

其實,f = function...f (x, y) = match (x, y) with...快捷方式,以便:

let f = function 
    | pattern1_of_x_y -> expr1 
    | ... 

是一樣的:

let f (x, y) = 
    match x, y with 
    | pattern1 -> expr1 
    | ... 

(注意這裏是你的第二個配方中的錯誤;這兩個版本都沒有兼容)。

正如您所指出的,人們不能避免在咖喱功能中使用match ... with...。就我個人而言,我更喜歡功能的咖喱形式,因爲它更靈活,特別是在部分應用中。此外,模式匹配不僅適用於函數參數,它們基本上在OCaml中隨處可見,這使得match ... with...的構造變得更加重要。

每當您發現上述使用模式時,請嘗試用function替換match ... with...。這只是一個風格問題,所以這裏沒有什麼比這更好的了。

8

該解決方案是規範:

let f x y = 
    match x, y with 
    | pattern1 -> expr1 
    | ... 

編譯器優化此特殊情況,並且實際上不分配的塊爲元組(x, y)

3

規範的方式是一個curried函數和match上的元組,即您的第一個片段。

這是標準庫的編寫方式(查看標準庫源代碼,例如list.ml中的許多函數)。

這也是實現優化的方式,尤其是本機代碼編譯器。如果您創建一個元組或其他塊並立即銷燬它,而不將它傳遞給期望塊的函數,本地代碼編譯器通常會發現它並避免完全分配塊。即使您最終分配了一個塊,將塊的持續時間儘可能短也會更有效,從而增加塊保留在次堆中和處理器高速緩存中的機會。

相關問題