You are dealing with immutable data-types (immutable list) here. This means lists are not changed, every operations creates and returns a new list.
Pattern Matching is a way to deconstruct data into multiple pieces. As an example. If you have the list [1;2;3;4]
and you write.
let list = [1;2;3;4]
let (head :: tail) = list
Then head
is the value 1
. tail
is the list [2;3;4]
and list
is still [1;2;3;4]
.
Let's go through your example step-by-step.
even [1;2;3;4]
is called. Then there are three cases with Pattern Matching. The first one checks if [1;2;3;4]
is an empty list. Its not so it checks the next one. head :: tail
extracts the list into two pieces like above. So head
is 1
and tail
represents [2;3;4]
, but when head % 2 = 0
adds a conditional. It checks if head
(currently 1
) is dividable by two. It isn't, so it goes to the last Pattern Matching.
The last one is _::tail
. First it does the exact same as head::tail
. It extracts the first value 1
and stores it in the variable _
. The reason to use _
as a variable name is to clarify that the first name is never used. You also could change _
to head
and the code works the same.
The last Pattern Match matches, and now you have 1
stored in _
and [2;3;4]
stored in tail
. And all you do is call even tail
. Or in that case, you call even [2;3;4]
and return the result of this function call as your result.
When even [2;3;4]
is called it does the same above.
It checks if its an empty list. It's not. Then it extract the first value 2
in head
and [3;4]
into tail
. It checks the when condition. This time it is true. So now it executes head :: even tail
Or if we replace the values we get 2 :: even [3;4]
::
is a concatenation of a list, but before we can concatenate a list, first the function call even [3;4]
needs to return a list. So even [3;4]
is called.
This then checks again.
- Is [3;4] an empty list. Nope.
- Is the
head
the value 3
dividable by 2. Nope.
- Extract
3
into _
and [4]
into tail
, and call even [4]
.
even [4]
then does the same:
- Is
[4]
an empty list. Nope.
- Is the value
4
assigned to head
an even number? Yes it is. So 4 :: even []
is called.
even []
then does the same:
- Is
[]
an empty list. Yes it is. So return the empty list. []
Then it goes backwards.
-> means "returns"
even [] -> []
4 :: even [] -> [4]
even [3;4] -> [4]
2 :: even [3;4] -> [2;4]
even [2;3;4] -> [2;4]
even [1;2;3;4] -> [2;4]