Iva*_*nin 7 erlang ocaml pattern-matching
我是OCaml的新手并且阅读了Real World OCaml(RWO)一书.模式匹配在第3章中描述,与Erlang(或Prolog)的模式匹配相比似乎很弱.
我的问题是:
一个具体的例子:
以下功能(取自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更严格(但也更难实现).
Erlang模式更强大,因为它可以匹配运行时确定的内容.OCaml模式与编译时修复的内容相匹配.因此,OCaml模式可能会变得更快.我也发现OCaml风格的模式更容易推理.