【问题标题】:OR pattern matching或模式匹配
【发布时间】:2012-06-12 04:26:23
【问题描述】:

我正在尝试使用 OR 模式,如 here 所述:

let foo = function
    | Some (0, x) when x > 0 | None -> "bar"
    | _ -> "baz"

但是,这会导致编译器错误:

错误 FS0010:意外符号“|”在模式匹配中。预期'->' 或其他令牌。

我做错了什么?和when守卫有关系吗?

【问题讨论】:

  • 谢谢,正在找这个。奇怪的是它没有被问太多。 Scala 更优雅地做到了这一点。

标签: f# pattern-matching


【解决方案1】:

when 守卫指的是单个案例,无论组合了多少模式。案例需要分开:

let foo = function
  | Some (0, x) when x > 0 -> "bar"
  | None -> "bar"
  | _ -> "baz"

因此,最好将返回值分解出来,这样就不会重复可能很复杂的表达式:

let foo value =
  let ret = "bar"
  match value with
  | Some (0, x) when x > 0 -> ret
  | None -> ret
  | _ -> "baz"

使用主动模式是避免此类重复的另一种方法:

let (|Bar|_|) = function
  | Some(0, x) when x > 0 -> Some()
  | None -> Some()
  | _ -> None

let foo = function
  | Bar -> "bar"
  | _ -> "baz"

【讨论】:

  • 主动模式也更干净,可以让你组合起来。
【解决方案2】:

您需要两个单独的匹配案例,因为这两个案例绑定了不同的变量集(分别为x 和什么都没有):

| Some(0, x) when x>0 -> "bar"
| None -> "bar"

【讨论】:

    【解决方案3】:

    当您只想以非常复杂的模式保护标签的特定绑定时,我有时会使用一个不错的技巧,即使用我自己的活动模式和 & (and) 模式运算符:

    let (|GreaterThan|_|) lowerLimit n =
        if n > lowerLimit then Some () else None
    
    let (|LesserThan|_|) upperLimit n =
        if n < upperLimit then Some () else None
    
    let (|GreaterOETo|_|) lowerLimit n =
        if n >= lowerLimit then Some () else None
    
    let (|LesserOETo|_|) upperLimit n =
        if n <= upperLimit then Some () else None
    
    let (|InRange|_|) (lowerLimit, upperLimit) n =
        if n >= lowerLimit && n <= upperLimit then Some () else None
    
    let (|Even|Odd|) n =
        if n % 2 = 0 then
            Even (n / 2)
        else
            Odd (n / 2)
    
    type Union =
        | A of int
        | B of int
        | A' of int
    
    let getSpecialCases = function
        | A (Even (x & GreaterThan 4 & LesserOETo 16))
        | A (Odd (x & GreaterThan 0))
        | B (x & LesserOETo 0)
        | A' (Even (x & InRange (5, 16)))
        | A' (Odd (x & GreaterThan 0)) -> Some x
        | _ -> None
    

    当然你也可以为活动模式包装器创建一个函数:

    let (|P|_|) pred x =
        if pred x then Some () else None
    
    let ``match`` = function
        | Even (x & pred (fun x -> x >= 7 && x <= 54)) -> Some x
        | _ -> None
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-08-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-03-10
      相关资源
      最近更新 更多