【问题标题】:Erlang pattern matching errorErlang 模式匹配错误
【发布时间】:2015-01-12 00:07:39
【问题描述】:

我最近开始学习Erlang,在尝试pattren match时遇到以下错误

以下表达式工作正常:

{A,_,[B|_],{B}}={abc,23,[22,x],{22}}.
Resulting in
A = abc
B = 22

以下表达式不起作用:

{A,_,[_|B],{B}}={abc,23,[22,x],{x}}.
Is resulting in 
** exception error: no match of right hand side value {abc,23,[22,x],{x}}

但是,如果我将 [22 , x 中的“,”替换为 |如下所示,它的工作查找并将 x 绑定到 B

{A,_,[_|B],{B}}={abc,23,[22|x],{x}}.
{abc,23,[22|x],{x}}
B.
x

对此的任何解释将不胜感激。

提前非常感谢

【问题讨论】:

  • [_|Whatever] 的字面意思是anything,所以它不能被匹配,因为_ 可以消费/匹配任何东西,包括匹配的整个元素.这意味着“任何东西,然后是Whatever——我们在这里没有定义”。 [22|Whatever] 或任何[FiniteThing|_] 表示“具体和有限的东西,然后是Whatever”,可以匹配,因为它可以完全匹配和消耗列表的第一部分。 IOW,“任何东西”匹配/消耗所有东西,而具体和有限的东西只能代表它自己。

标签: erlang pattern-matching


【解决方案1】:

您需要仔细研究| 运算符的工作原理。它基本上采用列表的头部,这是一个元素,并返回列表的尾部,这是其余的。和“all”一样,建议 tail 也是一个列表。它可以是一个元素列表,甚至可以是空列表,但它仍然是一个列表。

> [Head| Tail] = [23,x].
[23,x]
> Head.
23
> Tail
[x].

因此,在您的模式匹配中,您指定为尾部[x],而不是尝试简单地在x 上进行模式匹配。这就是失败的原因。

附注:您可以使用| 运算符创建新列表,但您应该谨慎执行此操作。因为你可以创建improper list(你可以使用[23 | x])。这就是您的“修复”有效的原因。

如果你想匹配两个元素列表,你可以明确地做到这一点

[A, B] =  [23, x].

但如果列表有更多或更少的元素,这将失败。

如果您只想匹配前两个元素,您仍然可以使用| 运算符。

> [A, B | Rest] = [23, x].
[23, x]
> A.
23
> B.
x
> Rest.
[].

只有一个元素或空列表才会失败。

【讨论】:

    【解决方案2】:

    运算符| 用于递归定义列表:[A|B] 表示您将元素A 添加到现有列表BA 是结果列表的第一个元素,称为头,B 是列表的其余部分,称为尾。 B也可以拆分为头尾,可以继续处理直到尾等于空列表[]

    运算符 , 是列表​​元素之间的分隔符,因此 [A,B] 是由 AB 两个元素组成的列表。

    这2个运算符可以组合:[A,B,C|D]是一个至少包含3个元素的列表,分别是ABC,还有一个尾部D可以为空。

    在您的测试中,您使用了另一种语法:[23|x]; 23 可以是列表的元素(实际上任何 erlang 术语都可以是列表的元素),但 x 是原子,不能是列表尾。这样做会破坏列表的递归定义,这种结构不经常使用,被称为不正确的列表。

    • 当您匹配[_|B][_,x] 时,您将[x] 分配给B,这与表达式后面的x 不匹配

    • 当您匹配[_|B][_|x] 时,您将x 分配给B,在表达式后面确实匹配到x,但正确的方式应该是

      李>
    • {A,_,[_|B],{B}}={abc,23,[22,x],{[x]}}.

    【讨论】:

    • 非常感谢您的详细解释
    猜你喜欢
    • 2014-06-27
    • 2018-12-08
    • 2011-08-14
    • 2011-06-17
    • 2013-08-15
    • 2011-09-29
    • 2010-12-13
    • 2014-07-26
    • 2015-02-09
    相关资源
    最近更新 更多