OCaml Pattern match with non-constants

后端 未结 3 691
天命终不由人
天命终不由人 2021-01-20 00:02

Is it possible to do pattern matching on variables instead of constant values:

# let x = 2 in
let y = 5 in
match 2 with
| x -> \"foo\"
| y -> \"bar\"
|         


        
相关标签:
3条回答
  • 2021-01-20 00:25

    A when guard is a bad idea here in my opinion. Beginners tend to over-use the pattern-matching syntax that they find convenient, and this result in subtle bugs in their application. For one person that will notice that "hey, | y -> .. here is not what I want", ten other persons will make the mistake and don't notice it directly.

    You should discourage such error-prone pattern. My personal advice to beginners is to never use when, and to only use pattern-matching to destructure values of an inductive datatype (such as lists, trees, options, etc.). Pattern-matching on integers is almost always a mistake.

    I recommend to use if ... then .. else if .. then .. else instead.

    if z = x then "foo"
    else if z = y then "bar"
    else "baz"
    

    When is it legitimate to use when? It is understandable to have one when the rest of the cases do benefit from pattern-matching (to test nested patterns, etc.), or when the test is performed on values resulting from deep destructuration of the matched value. It can often be translated away by merging two branches and using an if..then..else locally.

    One exampe where it is inconvenient to remove is the following (testing combined to destructuring):

    match foo with
    | (Baz x) when pred x -> ...
    | _ -> ... 
    
    0 讨论(0)
  • 2021-01-20 00:29

    You need when guard:

    let x = 2 in
    let y = 5 in
    match 2 with
    | z when z = x -> "foo"
    | z when z = y -> "bar"
    | _ -> "baz";;
    

    The error messages are very instructive. When you use:

    let x = 2 in
    ...
    match 2 with
    | x -> "foo"
    | ...
    

    the new value x shadows the value x in previous let-bound hence the first error message. Moreover, since the new x matches everything, two below patterns of y and _ are obviously redundant.

    Note that matching a constant (match 2 with) is not a good idea.

    0 讨论(0)
  • 2021-01-20 00:42

    A "when" guard is what you're looking for here:

    let x = 2 in
    let y = 5 in
    match 2 with
    | x' when x' = x -> "foo"
    | y' when y' = y -> "baz"
    | _ -> "baz" ;;
    

    ...though I'm not sure why you'd ever want to match with a constant.

    0 讨论(0)
提交回复
热议问题