Разве не | символ, используемый только для сопоставления с образцом.
Нет, оператор cons (конструктор), |
, можно использовать как для деконструкции списка с сопоставлением с образцом, так и для построения списка. Часто последняя строка функции будет:
my_func(tail, [Head|Acc])
В этой строке оператор cons создает список для второго аргумента. Второй аргумент - это список, который добавляет содержимое переменной Head
в начало списка Acc
.
Вот пример использования оператора cons как для деконструкции списка, так и для построения списка:
-module(a).
-compile(export_all).
get_evens(List) ->
get_evens(List, []). %% Add an empty list to the function call to accumulate the results.
get_evens([Head|Tail], Acc) when Head rem 2 == 0 -> %% deconstruct the first argument into Head and Tail
get_evens(Tail, [Head|Acc]); %% construct the second argument for the get_evens() function call
get_evens([_Head|Tail], Acc) ->
get_evens(Tail, Acc);
get_evens([], Acc) ->
lists:reverse(Acc).
В оболочке:
2> c(a).
{ok,a}
3> a:get_evens([1, 2, 3, 4, 5]).
[2,4]
4>
Единственная причина, по которой мы можем написать рекурсивные функции, которые заканчиваются, когда найден пустой список, состоит в том, что список можно определить так:
4> [1|[2|[3|[4|[5|[]]]]]].
[1,2,3,4,5]
Заметьте, как 5 сопоставляется с пустым списком: 5|[]
? Это означает, что когда вы доберетесь до конца списка, [LastElmt | Tail]
будет соответствовать LastElmt
до 5
и Tail
до []
, что означает, что мы можем сопоставить другое предложение функции при вызове get_evens(Tail, Acc)
, например :
get_evens([], Acc) ->
lists:reverse(Acc).