Misunderstanding the cons operator

This is a general question regarding the cons (|) operator in erlang. I am about to take a mock exam and this question exists:

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.

      

I am confused why the following input: ([[a], [b], a]) results in output: {[b], [a]}

Why is this? From my understanding, if the split from the second item in the list (which is an empty list, []) is the same as the first item, then the output will be: A2, A1. If the 3rd element of a becomes a list, [a], then the output will be {[a], [b]}. Why?

+3


source to share


3 answers


This is because a correct list assumes that the right side of the operator [... | ...]

will be a list. The items on the left are attached or retrieved the values ​​of the head items, which can be other lists too, it doesn't matter. The last item on the left side is on the right. This means that in this case the first element matches the tail list

[A1, A2 | A1] = [[a], [b], a] = [[a], [b] | [a]] = [[a], [b]] ++ [a].

You cannot write [a,b,c | d,e,f,g]

, you can only have one tail. But it [a,b,c | [d,e,f,g]]

will work and is equal [a,b,c,d,e,f,g]

. This means that you are creating a list item with a value a

that points to a value list item b

that points to a value list item c

that points to the right side (no matter what). Its equivalent (using only the |

no-comma operator ):

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

...



To understand this, you have to think about it rather than about commas. Binding example: [El1, El2 | Tail] = [a,b,c,d], [El1 | [El2 | Tail]] = [a,b,c,d].

In both cases, El1 = a, El2 = b

and Tail = [c,d] = [c | [d]] = [c | [d | []]]

.

As you can see, [[a],[b], a]

means that a value list item [a]

(which is a value list item a

that points to an empty list []

) points to a value list item [b]

that points to a value list item a

that points to an empty list []

.

Every correct last element of the list points to an empty list []

, so it is true that [a,b,c] == [a,b,c | []].

But there are also incorrect lists, and you can construct them using non list as a tail, like [a,b,c | d]

, but this is only useful in certain situations and most list operations cannot apply to them. One use case is lazy evaluation , where tail is a function.

I just found a similar question to yours, here . If it's not clear yet, you can find a wiki page about a separately linked list .

+3


source


([[a], [b] , a])

will match the first sentence f2([A1, A2 | A1]) -> {A2, A1};

.



so [A1, A2 | A1] = [[a], [b] , a]

you can get A1 = [a], A2 = [b]

important is the second A1

, A1 = [a]

.

0


source


Operator | is used to recursively define a list: [A | B] means you are adding item A to an existing list B. A is the first item in the resulting list called the head, B is the rest of the list called the tail. B can also be split into head and tail, and the process can continue until the tail is equal to the empty list [].

Your example can be written in different ways:

L = [[a], [b] , a]. % element list representation
L = [[a]|[[b]|[a|[]]]]. % cons list representation
L = [[a],[b]|[a]]. % mixed representation

      

In the latter case, you can recognize the pattern of the [A1, A2 | A1]

first sentence of the function f2 / 1 to get the result {A2,A1} = {[b],[a]}

.

0


source







All Articles