OCaml模式匹配中as关键字用法差异导致去重函数结果异常
OCaml模式匹配中
as绑定和普通列表拆分的差异说明 1. 两种模式的绑定逻辑差异
OCaml 中as关键字的作用是将它前面整个匹配到的模式对应的完整值绑定到指定变量,这是两种写法产生差异的核心原因:
- 对于
x :: (y :: _ as t):
匹配长度≥2的列表时,x绑定列表第一个元素,y绑定第二个元素,t绑定从第二个元素开始的完整剩余列表(包含y)。 - 对于
x :: (y :: t):
匹配长度≥2的列表时,x绑定列表第一个元素,y绑定第二个元素,t绑定第二个元素之后的剩余列表(不包含y)。
2. 示例执行流程对比
我们以输入["a"; "a";"b"; "c"; "c"]为例,分别走两种写法的执行逻辑:
正确版本(带as)
let rec compress l = match l with | [] -> [] | [x] -> [x] | x :: (y :: _ as t) -> if x = y then compress t else x :: compress t;;
执行步骤:
- 第一次匹配:
x="a",y="a",t=["a";"b";"c";"c"],x等于y,执行compress ["a";"b";"c";"c"] - 第二次匹配:
x="a",y="b",t=["b";"c";"c"],x不等于y,执行"a" :: compress ["b";"c";"c"] - 第三次匹配:
x="b",y="c",t=["c";"c"],x不等于y,执行"b" :: compress ["c";"c"] - 第四次匹配:
x="c",y="c",t=["c"],x等于y,执行compress ["c"] - 第五次匹配到单元素分支,返回
["c"]
最终拼接结果为["a"; "b"; "c"],符合预期。
错误版本(无as)
let rec compress l = match l with | [] -> [] | [x] -> [x] | x :: (y :: t) -> if x = y then compress t else x :: compress t;;
执行步骤:
- 第一次匹配:
x="a",y="a",t=["b";"c";"c"],x等于y,执行compress ["b";"c";"c"] - 第二次匹配:
x="b",y="c",t=["c";"c"],x不等于y,执行"b" :: compress ["c";"c"] - 第三次匹配:
x="c",y="c",t=[],x等于y,执行compress [] - 第四次匹配到空列表分支,返回
[]
最终拼接结果为["b"; "c"],丢失了开头的"a"元素。
3. 本质区别总结
- 带
as的写法中,每次去重递归时,会把重复的第二个元素保留在递归参数t中,避免连续重复的元素被整体丢弃 - 不带
as的写法中,每次遇到重复元素时,会直接跳过前两个元素递归,导致连续重复的元素全部被丢弃
内容的提问来源于stack exchange,提问作者hexaquark
相关产品推荐
相关产品推荐

