Erlang列表匹配

Vol*_*erK 5 erlang

我正在阅读" 在Erlang中思考"这本书.在"图10:案例示例"中,它有以下示例:

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

它说 :

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

但如果我真的匹配[_One,_Two | _Tail]一切仍然按预期工作.书中有错误还是我弄错了?

Nin*_*ing 8

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

的语义

[_One, _Two, _Three | _Tail]
Run Code Online (Sandbox Code Playgroud)

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

的语义

[_One, _Two | _Tail]
Run Code Online (Sandbox Code Playgroud)

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

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

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

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

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

因此,即使[ _One, _Two | _Tail ]在您的情况下工作,使用[ _One, _Two , _Three | _Tail ]被认为是一种很好的做法,以防您之后切换模式.