对运营商的误解

时间:2014-12-23 08:02:27

标签: list erlang

这是关于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]}。为什么呢?

3 个答案:

答案 0 :(得分:3)

这是因为在正确的列表中,[... | ...]运算符的右侧应该是一个列表。左边的元素是头元素的附加或提取值,也可以是其他列表,这没关系。左侧的最后一个元素指向右侧。这意味着在这种情况下,第一个元素匹配尾部列表

[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的list元素,该元素指向列出值b的元素,该元素指向列出值c的元素,该元素指向右侧(无论如何)。 它的等价物(仅使用不带逗号的|运算符)是:

[a | [b | [c | [d | [e | [f | [g]]]]]]]

要理解它,你应该用这种方式而不是用逗号来思考它。 绑定示例: [El1, El2 | Tail] = [a,b,c,d], [El1 | [El2 | Tail]] = [a,b,c,d]. El1 = a, El2 = bTail = [c,d] = [c | [d]] = [c | [d | []]]这两种情况下。

如您所见[[a],[b], a]表示值[a]的列表元素(值为a的列表元素,指向空列表[])指向列表值为[b]的元素,它指向值a的列表元素,该元素指向空列表[]

每个正确的列表最后一个元素指向空列表[]所以[a,b,c] == [a,b,c | []].是真的 但是也存在不正确的列表,您可以使用非列表作为尾部来构造它们[a,b,c | d],但这仅在特定情况下有用,并且大多数列表操作无法应用于它们。使用的一个示例是lazy evaluation,其中tail是函数。

我刚刚向你发现了类似的问题,它是here。 如果仍然不清楚,您可能会发现关于singly linked list的维基页面很有用。

答案 1 :(得分:0)

([[a], [b] , a])将匹配第一个条款f2([A1, A2 | A1]) -> {A2, A1};

所以[A1, A2 | A1] = [[a], [b] , a],您可以获得A1 = [a], A2 = [b],重要的是第二个A1A1 = [a]

答案 2 :(得分:0)

操作员|用于列表的递归定义:[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

在最后一个中,您可以识别f2 / 1函数第一个子句的模式[A1, A2 | A1],因此得到结果{A2,A1} = {[b],[a]}