为啥 OCaml 模式匹配比 Erlang 弱?
Posted
技术标签:
【中文标题】为啥 OCaml 模式匹配比 Erlang 弱?【英文标题】:Why is OCaml's pattern matching weaker than Erlang's?为什么 OCaml 模式匹配比 Erlang 弱? 【发布时间】:2016-04-29 14:27:03 【问题描述】:我是 OCaml 的新手,正在阅读 Real World 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 方法的优点是什么?
感谢和祝福
伊万
【问题讨论】:
【参考方案1】:首先,您始终可以通过 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 不仅已经内置了 =
与 ==
(结构平等与身份),而且对于任何给定类型,它可能不是您需要的那种平等(例如,考虑字符串和区分大小写)。然后,因此,检查详尽或重叠变得不平凡。最后,考虑到模式的各个部分之间可能存在多少有用的关系,是否值得为一种特定类型的相等提供特殊情况是值得怀疑的。 (我注意到非严格语言还有其他问题。)
顺便说一句,Prolog 的模式匹配是基于统一的,并且比 Erlang 或 OCaml 更强大(但也更难实现)。
【讨论】:
感谢您的回答!三个非常好的答案,很难决定接受哪个。 -- when 子句在 Erlang 中也可用(称为守卫)。 RWO 书中稍后会出现一个与您类似的示例,但我会想念 Erlang 风格的 PM :(【参考方案2】:OCaml 中的模式被编译成具有大量sophisticated optimizations 的非常高效的代码。 Bjarne Stroustrup 甚至 bragged 他们设法在某些情况下用 C++ 编写了类似的东西。但总的来说,OCaml 模式匹配要快得多。看看汇编输出很有趣。也许 Erlang 提供了更多的灵活性,但这是一种动态语言所期望的。否则,为什么要使用它们。
还有另一个问题。模式在结构上是匹配的。如果你想匹配[H,H|T]
,你实际上是在调用前两个元素的比较。大多数情况下,比较功能应该是用户自己提供的,事先并不知道。
【讨论】:
【参考方案3】:Erlang 模式更强大,因为它可以匹配在运行时确定的内容。 OCaml 模式与编译时固定的内容相匹配。因此,OCaml 模式可能会变得更快。我还发现 OCaml 样式的模式更容易推理。
【讨论】:
感谢您的回答!三个非常好的答案,很难决定接受哪个。 -- 你发现OCaml 风格的模式更容易推理,因为你对OCaml 比对Erlang 更熟悉?我如何才能爱上来自 Erlang 的 OCaml PM?以上是关于为啥 OCaml 模式匹配比 Erlang 弱?的主要内容,如果未能解决你的问题,请参考以下文章