我最近开始学习Erlang,并在尝试匹配时遇到以下错误
以下表达式正常工作:
{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
对此的任何解释都将受到高度赞赏。
非常感谢提前
答案 0 :(得分:1)
您需要仔细研究|
运算符的工作原理。它基本上是列表的头部,这是一个元素,并返回列表的尾部,这是其余的。并且喜欢"所有"建议尾巴也是一个清单。它可能是一个元素列表,它甚至可能是空列表,但它仍然是一个列表。
> [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.
[].
这只会在单元素或空列表中失败。
答案 1 :(得分:1)
运算符|
用于列表的递归定义:[A|B]
表示您将元素A
添加到现有列表B
。 A
是结果列表的第一个元素,称为head,B
是名为tail的列表的其余部分。 B
也可以分为头部和尾部,并且该过程可以继续,直到尾部等于空列表[]
。
运算符是列表元素之间的分隔符,因此[A,B]
是包含2个元素A
和B
的列表。
可以合并2个运算符:[A,B,C|D]
是至少3个元素的列表,A
,B
和C
以及尾{{1}这可能是空的。
在测试中,您使用了另一种语法:D
; 23可以是列表的元素(实际上任何erlang术语都可以是列表的元素)但是x是原子并且不能是列表尾部。这样做打破了列表的递归定义,这种结构不经常使用,被称为不正确的列表。
当您匹配[23|x]
和[_|B]
时,您将[_,x]
分配给[x]
,而B
与x
后面的表达式不匹配
当您与[_|B]
和[_|x]
匹配时,您将x
分配给B
,该x
确实与表达式后面的{A,_,[_|B],{B}}={abc,23,[22,x],{[x]}}.
匹配,但是正确的方法应该是
{{1}}