【问题标题】:Erlang list matchingErlang 列表匹配
【发布时间】:2012-06-08 17:14:44
【问题描述】:

我正在阅读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 ] 一切仍然按预期工作。是书上的错误还是我有什么问题?

【问题讨论】:

    标签: erlang


    【解决方案1】:

    我认为这可能不是错误。

    语义

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

    【讨论】:

      【解决方案2】:

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

      【讨论】:

        猜你喜欢
        • 2014-04-09
        • 1970-01-01
        • 1970-01-01
        • 2011-11-10
        • 2016-10-27
        • 1970-01-01
        • 2014-06-27
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多