OCaml未來的4.03版本增加了一個新的警告57
,以防止ambiguous guarded pattern。也就是說,問題是,如果when
子句的or模式中,如果or-pat的第一部分匹配,但when
的計算結果爲false
,則完整模式將被丟棄,但or-pat的另一個變體可能會被丟棄已成功。例如,在下面的代碼,ko
將被綁定到1
,這可奇怪:含糊不清的圖案
type t = A of string | B of string
let bad x y =
match x,y with
| A s, _ | _, A s when s = "foo" -> 0
| _, _ -> 1
let ok = bad (A "foo") (A "bar")
let ko = bad (A "bar") (A "foo")
在4.03,OCaml中將會Warning 57: Ambiguous guarded pattern, variable s may match different or-pattern arguments
抱怨,建議你檢查你是否真的打算這種行爲或沒有。
但是,警告也對在以下定義的模式匹配的第二行活性:
let f x y =
match x,y with
| A _, A _ -> 0
| A s, _ | _, A s when s = "foo" -> 1
| _ -> 2
在這裏,我認爲,歧義不能出現,因爲A _, A _
由第一匹配因此,如果程序到達這一點,那麼or或pattern中至多有一個組件可以匹配。這個推理是否正確?
如果答案是肯定的,我想另外知道是否可以在此特定分支上使此警告無聲。事實上,我可以做match [@warning "-57"] x,y with
,但是如果有人稍後在別處引入另一個模糊的模式,這將會使警告消失。我試圖將該屬性置於模式級別(| A s, _ | _, A s [@warning "-57"] when s = "foo"
),但這不起作用。
注意:我知道在這個特定情況下,我可以用| A s, B _ | B _, A s when s = "foo"
來代替catch-all來消除歧義,但考慮到這只是一個簡化的例子。
我並不是建議編譯器應該更聰明,我只想告訴它:「相信我這個特定的模式_我知道我在做什麼」,而不必放棄警告用於整個模式匹配表達式。 – Virgile
我想一個指令打開或關閉本地警告將是有用的。 –