[英]Misunderstanding of the cons operator
这是关于erlang中cons(|)运算符的一般性问题。 我正在参加一个样本考试并且存在这个问题:
f2([A1, A2 | A1]) ->
{A2, A1};
f2([A, true | B]) ->
{A, B};
f2([A1, A2 | _]) ->
{A1, A2};
f2([_ | B]) ->
[B];
f2([A]) ->
{A};
f2(_) ->
nothing_matched.
我很困惑为什么以下输入:([[a],[b],a])导致输出:{[b],[a]}
为什么是这样? 根据我的理解,如果从列表中的第二个元素(这是空列表,[])的拆分与第一个元素相同,那么输出将是:A2,A1。 如果第3个元素a成为列表[a],则输出为:{[a],[b]}。 为什么?
这是因为在正确的列表中[... | ...]
的右侧] [... | ...]
运算符应该是一个列表。 左边的元素是头元素的附加或提取值,也可以是其他列表,这没关系。 左侧的最后一个元素指向右侧。 这意味着在这种情况下,第一个元素与尾部列表匹配
[A1, A2 | A1] = [[a], [b], a] = [[a], [b] | [a]] = [[a], [b]] ++ [a].
你不能写[a,b,c | d,e,f,g]
[a,b,c | d,e,f,g]
,你只能有一条尾巴。 但是[a,b,c | [d,e,f,g]]
[a,b,c | [d,e,f,g]]
将起作用并且等于[a,b,c,d,e,f,g]
。 这意味着你构造a
值为a
列表元素,它指向值b
列表元素,它指向值c
列表元素,它指向右侧(无论如何)。 它的等价物(仅使用没有逗号的|
运算符)是:
[a | [b | [c | [d | [e | [f | [g]]]]]]]
[a | [b | [c | [d | [e | [f | [g]]]]]]]
。
要理解它,你应该用逗号来思考它。 绑定示例: [El1, El2 | Tail] = [a,b,c,d], [El1 | [El2 | Tail]] = [a,b,c,d].
[El1, El2 | Tail] = [a,b,c,d], [El1 | [El2 | Tail]] = [a,b,c,d].
在两种情况下, El1 = a, El2 = b
, Tail = [c,d] = [c | [d]] = [c | [d | []]]
Tail = [c,d] = [c | [d]] = [c | [d | []]]
Tail = [c,d] = [c | [d]] = [c | [d | []]]
。
如您所见[[a],[b], a]
表示值[a]
列表元素(值为a
列表元素,指向空列表[]
)指向值[b]
的列表元素它指向值a
的列表元素,该元素指向空列表[]
。
每个正确的列表最后一个元素指向空列表[]
所以确实[a,b,c] == [a,b,c | []].
[a,b,c] == [a,b,c | []].
但是也有不正确的列表,您可以使用非列表作为尾部来构造它们,如[a,b,c | d]
[a,b,c | d]
但这仅在特定情况下有用,并且大多数列表操作无法应用于它们。 使用的一个示例是延迟评估 ,其中tail是函数。
([[a], [b] , a])
将匹配第一个子句f2([A1, A2 | A1]) -> {A2, A1};
。
所以[A1, A2 | A1] = [[a], [b] , a]
[A1, A2 | A1] = [[a], [b] , a]
,你可以得到A1 = [a], A2 = [b]
,重要的是第二个A1
, A1 = [a]
。
操作员| 用于列表的递归定义:[A | B]表示将元素A添加到现有列表B.A是结果列表的第一个元素,称为头,B是列表的其余部分,称为尾巴。 B也可以分为头部和尾部,并且该过程可以继续,直到尾部等于空列表[]。
您的示例可以用不同的方式编写:
L = [[a], [b] , a]. % element list representation
L = [[a]|[[b]|[a|[]]]]. % cons list representation
L = [[a],[b]|[a]]. % mixed representation
在最后一个中,您可以识别模式[A1, A2 | A1]
在f2 / 1函数的第一个子句的[A1, A2 | A1]
中,得到结果{A2,A1} = {[b],[a]}
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.