Erlang列表匹配

标签 erlang

我正在阅读这本书 Thinking in Erlang .
在“图 10:案例示例”中有以下示例:

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

它说 :

If you are wondering why line 9 is not a match against [ _One, _Two | _Tail ], review the list matching rules for list tails at the end of the previous section.



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

最佳答案

我认为这可能不是错误。

的语义

[_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 ]被认为是一种很好的做法,以防您之后切换模式。

关于Erlang列表匹配,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10884564/

相关文章:

Erlang:新的实用程序函数,可从已知的记录集中获取记录的字段名称

erlang - 基本的 Erlang 问题

python - Erlang 和 Python 之间的 RSA 加密

erlang - 在 Erlang 中过度使用守卫?

erlang - 节点列表的应用环境值怎么写?

erlang - 匹配规范只能用于跟踪和从 ets 表中选择吗?可以在 case 表达式中使用它们吗?

java - 从 Java 获取 Ping 到 Erlang

erlang - 使用rebar释放时如何处理deps?

erlang - 处理 gen_server 状态的清理

file - Erlang 文件 I/O : Large binary files and gzip streaming