type foo = A of int * int | B of (int * int)
int * int
和(int * int)
之間有什麼區別?我看到的唯一區別是模式匹配:OCaml中的int * int vs(int * int)和類型
let test_foo = function
| A (f, s) -> (f, s)
| B b -> b
它只是一個語法糖嗎?你如何選擇使用哪一個?這兩種形式之間有什麼表現差異?
type foo = A of int * int | B of (int * int)
int * int
和(int * int)
之間有什麼區別?我看到的唯一區別是模式匹配:OCaml中的int * int vs(int * int)和類型
let test_foo = function
| A (f, s) -> (f, s)
| B b -> b
它只是一個語法糖嗎?你如何選擇使用哪一個?這兩種形式之間有什麼表現差異?
是的,有一個性能差異:
在存儲器A (23, 42)
將包含標籤標識它作爲一個A
和兩個整數23與42 B (23, 42)
將包含標籤標識它作爲一個B
和指向包含整數23
和42
的元組。因此,在創建B
時會有一個額外的內存分配,並且在訪問B
內部的各個值時會有一個額外的間接級別。因此,如果您實際上並未將構造函數參數用作元組,則使用A
將比使用B
花費更少的開銷。
在另一方面你test_foo
功能將創建一個新的記錄每次調用與A
值的時間,但是當它被稱爲一個B
值將簡單的返回已經存在於內存中的元組。因此test_foo
對於B
比A
更便宜。因此,如果您將構造函數的參數用作元組,並且您將多次使用相同的值,則使用B
將會更便宜。
所以如果你打算使用構造函數參數作爲元組,那麼使用構造函數來獲取元組是有意義的,因爲你可以通過使用少量代碼的模式匹配來獲得元組,並且因爲它可以避免必須多次創建來自相同值的元組。在所有其他情況下,不使用元組更好,因爲它涉及較少的內存分配和較少的間接。
它們是兩種不同的類型。該語法的解釋在*
運算符處不明確。它可被還原成以下形式:
int * int
與
type
關鍵字相關聯
type x = Y * Z
其中*
是在構造了一個元組操作者的能力使用
默認優先級將其轉換爲前者。通過圍繞(int * int)
放置括號,可以覆蓋默認優先級並強制執行後面的解釋。
如前所述,A
的構造函數需要兩個int
,而B
的構造函數需要一個有序對。
所以你可以寫
let bar = A (1, 2)
或
let bar = B (1, 2)
或
let bar = (1, 2)
let baz = B bar
,但你不能寫
let bar = (1, 2)
let baz = A bar
此外,在你的模式匹配,你仍然可以B的內容相匹配的兩個int,但不能A的內容相匹配的綁定到一個有序對
let test_foo = function
| A a -> a (* wrong *)
| B (f, s) -> (f, s) (* ok *)
這是棘手的事情在一個價值OCaml語法 - 即使它看起來像使用元組數據類型(A of int * int
)聲明構造函數,並且即使在使用構造函數時,它看起來像是給它一個元組(A (2,3)
),但實際上並非如此發生什麼事。
如果實際構造一個元組值並嘗試將其傳遞給構造函數,它將不會編譯 - let x = (2,3) in A x
。相反,構造函數定義中的*
和構造函數use表達式中的(,)
只是多個參數的構造函數的語法。語法模仿具有元組參數的構造函數,但實際上是分開的。如果你想用一個元組參數實際構造一個構造函數,額外的括號是必須的。
很好的問題。 – didierc 2013-02-11 20:33:52