When I stared looking into functional programming languages it was a big surprise for me that if statement and while/for/foreach loops were not only control flow structures to get things done.
More over in functional languages there is no such a thing as loops (At least it is not an idiomatic approach). Beside that using if statement is not quite idiomatic there as well. Developers rather prefer to use pattern matching.
Let's write a simple Elixir count method, which counts a numer of elements in a list. This example demonstrates us two fundamental things: pattern matching (instead of ifs) and recursion (instead of loops).
defmodule MyEnum do
def count([h|t]), do: 1 + count(t)
def count([]), do: 0
end
An example:
iex> MyEnum.count [:one,:two,:three]
The method has two patterns to match a list with elements and an empty list. If parameter is an empty list recursion is being stopped, otherwise list is being splitted into head and tail - [h|t]. If [h|t] matches this means that we can increment counter and call count recursivelly passing tail as a parameter.
Let's look under the hood:
iex> MyEnum.count [:one,:two,:three]
- a method with [h|t] pattern is being triggered.
- h = :one
- t = [:two,:three].
- call chain = 1 + count([:two,:three])
- a method with [h|t] pattern is being triggered again.
- h = :two
- t = [:three].
- call chain = 1 + (1 + count([:three])
- a method with [h|t] pattern is still being triggered.
- h = :three
- t = [].
- call chain = 1 + (1 + (1 + count([]))
- a method with [] pattern is being triggered. This method stops the recurrsion by returning zero.
- call chain = 1 + (1 + (1 + 0)
- Plus operator is being applied to the argument and the final result is three.