Erlang列表匹配

时间:2012-06-04 16:17:38

标签: erlang

我正在完成这本书Thinking in Erlang。 在“图10:案例示例”中,它有以下示例:

many(X) ->
case X of
    [] ->
        none;
    [ _One ] ->
        one;
    [ _One, _Two ] ->
        two;
    [ _One, _Two , _Three | _Tail ] ->
        many
end.

它说:

  

如果你想知道为什么第9行不匹配[_One,_Two | _Tail],查看上一节末尾列表尾的列表匹配规则。

但如果我真的与[_One,_Two | _Tail]一切仍然按预期工作。书中是否有错误或我出错?

2 个答案:

答案 0 :(得分:8)

我认为这可能不是一个错误。

的语义
[_One, _Two, _Three | _Tail]

是三个或更多元素的列表。

的语义
[_One, _Two | _Tail]

是两个或更多元素的列表。

由于第三种模式[ _One, _Two ]已经表明“两个元素列表”的情况,因此使用[_One, _Two | _Tail]会有点多余。

“一切都按预期工作”是有原因的。如果我们将第四个模式放在第三个模式之前,则给出:

many(X) ->
  case X of
    [] ->
      none;
    [_One] ->
      one;
    [_One, _Two | _Tail] ->  %% Switched
      many;
    [_One, _Two] ->          %% Switched
      two
  end.

然后一切都不会按预期工作。 Mod:many([a,b])会产生many而不是预期的two。这是因为当评估“case”表达式时,X依次与所有模式匹配。并且这个顺序保证。系统会返回many,因为[a,b]首先与[_One, _Two | _Tail]匹配,_Tail[](空列表)。

因此,即使[ _One, _Two | _Tail ]适用于您的情况,使用[ _One, _Two , _Three | _Tail ]也是一种很好的做法,以防您以后切换模式。

答案 1 :(得分:2)

这本书中的“错误”。我认为他们忘记了之前匹配的两个元素。但是,对于维护而言,尽可能使用匹配规则尽可能具体,因此如果要匹配“三个或更多元素”,请具体说明并按照书中的说明进行操作。有人可能会在将来删除以前的规则,或者出于任何原因重新排序它们。