为什么OCaml的模式匹配弱于Erlang?

时间:2016-01-22 21:09:56

标签: erlang pattern-matching ocaml

我是OCaml的新手并阅读了Real World OCaml(RWO)一书。模式匹配在第3章中描述,与Erlang(或Prolog)的模式匹配相比似乎很弱。

我的问题是:

  1. 为什么OCaml的模式匹配较弱?
  2. OCaml的模式匹配风格有什么优势吗?
  3. 一个具体的例子:

    以下功能(取自RWO第63页)降级列表

    let rec destutter list =
        match list with
        | [] -> []
        | [hd] -> [hd]
        | hd :: hd' :: tl ->
          if hd = hd' then ds1 (hd' :: tl)
          else hd :: ds1 (hd' :: tl)
      ;;
    
    # destutter [1;2;3;3;4;5;5;6];;
    - : int list = [1; 2; 3; 4; 5; 6]
    

    在Erlang中,有可能(我认为首选)使用模式匹配而不是条件:

    destutter([])      -> [];
    destutter([X])     -> [X];
    destutter([H,H|T]) -> destutter([H|T]);
    destutter([H|T])   -> [H | destutter(T)].
    

    在OCaml中尝试这种事情......

    let rec destutter list =
        match list with
        | [] -> []
        | [hd] -> [hd]
        | hd :: hd :: tl -> destutter tl  (* error *)
        | hd :: tl -> hd :: destutter tl
      ;;
    

    ...在标记的行上引发错误:

    Error: Variable hd is bound several times in this matching
    

    因此,Erlang / Prolog风格的模式匹配在OCaml中不起作用。为什么? OCaml方法有哪些优点?

    感谢和祝福

    伊万

3 个答案:

答案 0 :(得分:10)

首先,您始终可以通过OCaml中的when子句捕获模式变量之间的相等性,例如:

let rec destutter = function
    | []              -> []
    | [hd]            -> [hd]
    | hd :: hd' :: tl
      when hd = hd'   -> destutter (hd :: tl)
    | hd :: hd' :: tl -> hd :: destutter (hd' :: tl)

这里有一个权衡。虽然Erlang更具表现力,但OCaml模式匹配更简单(这意味着更简单的语言定义,编译器等),你仍然可以做你需要的(以编写更多代码为代价)。

请注意,虽然您可以使用when子句将非线性模式重写为线性模式,但这不是主要问题。更重要的是,模式匹配需要具有任意类型的相等概念,以支持非线性模式。这在Erlang中不是问题,但OCaml不仅内置= vs ==(结构相等与身份相同),但对于任何给定类型,它可能不是那种平等您需要的(例如,考虑字符串和区分大小写)。然后,结果,检查穷举或重叠变得非常重要。最后,考虑到模式各部分之间有多少有用的关系,为一种特定类型的平等提供特殊情况是否值得,这是值得怀疑的。 (我注意到非严格的语言有其他问题。)

顺便说一下,Prolog的模式匹配是基于统一的,并且比Erlang或OCaml更强大(但也更难以实现)。

答案 1 :(得分:7)

OCaml中的模式被编译成一个非常有效的代码,有很多sophisticated optimizations。 Bjarne Stroustrup甚至bragged他们设法在某些情况下用C ++编写了类似的东西。但总的来说,OCaml模式匹配的速度要快得多。而且看起来装配输出很迷人。也许Erlang提供了更多的灵活性,但它是通过动态语言实现的。否则为什么要使用它们。

还有其他问题。模式在结构上是匹配的。如果你想匹配[H,H|T],你实际上正在调用前两个元素的比较。在大多数情况下,比较功能应由用户提供,并且事先不知道。

答案 2 :(得分:6)

Erlang模式更强大,因为它可以匹配运行时确定的内容。 OCaml模式与编译时修复的内容相匹配。因此,OCaml模式可能会变得更快。我也发现OCaml风格的模式更容易推理。