为什么 OCaml 的模式匹配比 Erlang 的弱?
Why is OCaml's pattern matching weaker than Erlang's?
我是 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-style 模式匹配在 OCaml 中不起作用。为什么? OCaml 方法的优点是什么?
感谢和祝福
伊万
Erlang 模式更强大,因为它可以匹配 运行 时确定的内容。 OCaml 模式与编译时固定的内容相匹配。因此,可以使 OCaml 模式运行得更快。我还发现 OCaml-style 模式更容易推理。
OCaml 中的模式被编译成非常高效的代码,其中包含许多 sophisticated optimizations. Bjarne Stroustrup even bragged,在某些情况下,他们设法在 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)
这里有个trade-off。虽然 Erlang 更具表现力,但 OCaml 模式匹配更简单(这意味着更简单的语言定义、编译器等),您仍然可以做您需要的(以编写更多代码为代价)。
请注意,虽然您可以将 non-linear 模式重写为带有 when 子句的线性模式,但这不是主要问题。更关键的是,模式匹配需要对任意类型具有相等性的概念,以支持 non-linear 模式。这在 Erlang 中不是问题,但 OCaml 不仅已经有了 =
vs ==
built-in(结构相等 vs. 身份),而且对于任何给定的类型,它可能不是那种您需要的相等性(例如,考虑字符串和 case-sensitivity)。然后,因此,检查详尽性或重叠性变为 non-trivial。最后,考虑到一个模式的各个部分之间可以有多少有用的关系,为一种特定类型的相等性提供一个特例是否值得值得怀疑。 (我注意到 non-strict 语言还有其他问题。)
顺便说一句,Prolog 的模式匹配 unification-based 严格来说比 Erlang 或 OCaml 更强大(但也更难实现)。
我是 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-style 模式匹配在 OCaml 中不起作用。为什么? OCaml 方法的优点是什么?
感谢和祝福
伊万
Erlang 模式更强大,因为它可以匹配 运行 时确定的内容。 OCaml 模式与编译时固定的内容相匹配。因此,可以使 OCaml 模式运行得更快。我还发现 OCaml-style 模式更容易推理。
OCaml 中的模式被编译成非常高效的代码,其中包含许多 sophisticated optimizations. Bjarne Stroustrup even bragged,在某些情况下,他们设法在 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)
这里有个trade-off。虽然 Erlang 更具表现力,但 OCaml 模式匹配更简单(这意味着更简单的语言定义、编译器等),您仍然可以做您需要的(以编写更多代码为代价)。
请注意,虽然您可以将 non-linear 模式重写为带有 when 子句的线性模式,但这不是主要问题。更关键的是,模式匹配需要对任意类型具有相等性的概念,以支持 non-linear 模式。这在 Erlang 中不是问题,但 OCaml 不仅已经有了 =
vs ==
built-in(结构相等 vs. 身份),而且对于任何给定的类型,它可能不是那种您需要的相等性(例如,考虑字符串和 case-sensitivity)。然后,因此,检查详尽性或重叠性变为 non-trivial。最后,考虑到一个模式的各个部分之间可以有多少有用的关系,为一种特定类型的相等性提供一个特例是否值得值得怀疑。 (我注意到 non-strict 语言还有其他问题。)
顺便说一句,Prolog 的模式匹配 unification-based 严格来说比 Erlang 或 OCaml 更强大(但也更难实现)。