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

Iva*_*nin 7 erlang ocaml pattern-matching

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

我的问题是:

  1. 为什么OCaml的模式匹配较弱?
  2. 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]
Run Code Online (Sandbox Code Playgroud)

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

destutter([])      -> [];
destutter([X])     -> [X];
destutter([H,H|T]) -> destutter([H|T]);
destutter([H|T])   -> [H | destutter(T)].
Run Code Online (Sandbox Code Playgroud)

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

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

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

Error: Variable hd is bound several times in this matching
Run Code Online (Sandbox Code Playgroud)

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

感谢和祝福

伊万

Rei*_*nds 10

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

let rec destutter = function
    | []              -> []
    | [hd]            -> [hd]
    | hd :: hd' :: tl
      when hd = hd'   -> destutter (hd :: tl)
    | hd :: hd' :: tl -> hd :: destutter (hd' :: tl)
Run Code Online (Sandbox Code Playgroud)

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

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

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


ivg*_*ivg 7

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

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


Jef*_*eld 6

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

  • 感谢您的回答!三个非常好的答案,很难决定接受哪个. - 你发现OCaml风格的模式更容易推理,因为你比使用Erlang更熟悉OCaml?我怎样才能爱上来自Erlang的OCaml PM? (3认同)