为什么OCaml';s模式匹配弱于Erlang';s

为什么OCaml';s模式匹配弱于Erlang';s,erlang,pattern-matching,ocaml,Erlang,Pattern Matching,Ocaml,我刚接触OCaml,正在阅读真实世界的OCaml(RWO)书籍。模式匹配在第3章中进行了描述,与Erlang(或Prolog)的模式匹配相比似乎较弱 我的问题是: 为什么OCaml的模式匹配较弱 OCaml的模式匹配风格有什么优势吗 一个具体的例子: 下面的函数(摘自RWO第63页)取消列表输出 let rec destutter list = match list with | [] -> [] | [hd] -> [hd] | hd :: hd'

我刚接触OCaml,正在阅读真实世界的OCaml(RWO)书籍。模式匹配在第3章中进行了描述,与Erlang(或Prolog)的模式匹配相比似乎较弱

我的问题是:

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

    下面的函数(摘自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方法的优点是什么

    致以感谢和良好的祝愿


    Ivan

    Erlang模式更强大,因为它可以与运行时确定的内容相匹配。OCaml模式与编译时固定的内容相匹配。因此,可以使OCaml模式运行得更快。我还发现OCaml样式的模式更容易推理。

    OCaml中的模式被编译成一个非常高效的代码,其中包含大量代码。Bjarne Stroustrup甚至在C++中设法编写了一些类似的东西。但一般来说,OCaml模式匹配要快得多。看到汇编输出是很有吸引力的。也许Erlang提供了更大的灵活性,但它是一种动态语言。否则,为什么要使用它们呢


    还有一个问题。模式在结构上是匹配的。如果要匹配
    [H,H | T]
    ,实际上是调用前两个元素的比较。在大多数情况下,比较函数应由用户提供,并且事先不知道。首先,您可以通过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
    =
    功能(结构相等vs.标识),而且对于任何给定类型,它可能不是您需要的相等类型(例如,考虑字符串和大小写敏感度)。因此,检查是否详尽或重叠就变得非常重要。最后,考虑到模式各部分之间可能存在多少有用的关系,为一种特定类型的等式提供一个特例是否值得值得值得值得一试是值得怀疑的。(我注意到非严格语言还有其他问题。)


    另外,Prolog的模式匹配是基于统一的,严格来说比Erlang或OCaml更强大(但也更难实现)。

    谢谢您的回答!三个非常好的答案,很难决定接受哪一个当Erlang中也有子句时(称为guards)。在RWO的书中稍晚会出现一个类似于您的示例,但我将错过Erlang风格的PM:(感谢您的回答!三个非常好的答案,很难决定接受哪一个。--您发现OCaml风格的模式更容易推理,因为您对OCaml比对Erlang更熟悉?我如何才能爱上来自Erlang的OCaml PM?