2016-02-19 59 views
2

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來消除歧義,但考慮到這只是一個簡化的例子。

回答

1

警告是人們不知道when警衛不是模式的一部分,並想象A s, _ | _, A s when s = ""是相同的A s, _ | (_, A s when s = "")這是語法上無效。

保持警告似乎是一個好主意,但如果明確的括號阻止了它,那將是很好的,例如, (A s, _ | _, A s) when s = ""

您建議編譯器應該比普通讀者更聰明,並且基於非顯而易見的規則來抑制警告。換句話說,你的推理是正確的,但對於習慣依賴警告的程序員而言,開銷太大。

+0

我並不是建議編譯器應該更聰明,我只想告訴它:「相信我這個特定的模式_我知道我在做什麼」,而不必放棄警告用於整個模式匹配表達式。 – Virgile

+0

我想一個指令打開或關閉本地警告將是有用的。 –