Erlang模式匹配中同名变量是否值相等?能否简化匹配代码?
Erlang模式匹配中同名变量的含义及代码改写分析
首先明确核心问题:在Erlang的模式匹配规则里,同一个函数子句中出现的同名变量,要求它们绑定的值必须完全相同。这是Erlang模式匹配的核心特性之一——变量在子句中第一次绑定后,后续出现的同名变量会自动检查是否和之前的绑定值一致,不一致则该模式匹配失败。
接下来看你的代码改写思路:这个方向是可行的,但你写的版本逻辑搞反了,我们来拆解清楚:
原代码逻辑回顾
原代码通过when守卫区分两种情况:
% 情况1:两个列表头元素不相等,距离+1后递归 hdistance([H|T], [H1|T1], Distance) when H /= H1 -> hdistance(T, T1, Distance + 1); % 情况2:两个列表头元素相等,距离不变直接递归 hdistance([H|T], [H1|T1], Distance) when H == H1 -> hdistance(T, T1, Distance).
正确的无守卫改写方式
利用Erlang模式匹配的同名变量特性,我们可以去掉when子句,但需要调整子句顺序和逻辑:
% 匹配两个列表头相等的情况(等价于原代码的H == H1),距离不变 hdistance([H|T], [H|T1], Distance) -> hdistance(T, T1, Distance); % 匹配剩余的两个非空列表情况(此时头必然不相等,等价于原代码的H /= H1),距离+1 hdistance([H|T], [H1|T1], Distance) -> hdistance(T, T1, Distance + 1).
为什么这样可行?
- 第一个子句的模式
[H|T], [H|T1]中,变量H需要同时匹配两个列表的头元素。只有当两个头元素的值完全相同时,这个模式才能匹配成功(Erlang不允许同一子句内同名变量绑定不同值),这正好对应原代码中when H == H1的条件。 - 由于Erlang会按顺序匹配函数子句,第一个子句已经处理了头相等的情况,第二个子句就只会匹配头不相等的非空列表,完全等价于原代码中
when H /= H1的分支。
你最初写的版本把两个分支的逻辑搞反了(头相等时反而加了距离),所以会得到错误的结果,但只要调整分支的逻辑和顺序,完全可以用模式匹配替代守卫条件。
内容的提问来源于stack exchange,提问作者Muhammad Lukman Low
相关产品推荐
相关产品推荐

