Manage the zoo with pipes
Try it yourself!
Functions to categorize animals
is_bird? = fn
"🦉" -> true
"🦩" -> true
_other -> false
end
is_brown? = fn
"🦉" -> true
"🐻" -> true
_other -> false
end
We have the following animals in our zoo
animals = ["🦉", "🦉", "🦩", "🦩", "🦩", "🐻", "🐻"]
How many brown birds are there?
Filter all the birds
birds = Enum.filter(animals, is_bird?)
Filter all brown animals from the birds
brown_birds = Enum.filter(birds, is_brown?)
Count the brown birds and print the result
"Number of brown birds: #{length(brown_birds)}"
The pipe operator
The pipe operator is written as |>
. It links the result of the expression on the left side of the pipe to the function on the left side. It does this by passing the result of the expression to the functions as first argument. The following:
length(animals)
Is therefore the same as this:
animals |> length()
A function that is piped into can have multiple arguments. The pipe will always provide the result from the expression to the left of the pipe as first argument to the function on the rigt of the pipe. The other arguments must be provided manually.
animals |> Enum.filter(is_bird?)
Here the list of animals is provided to the Enum.filter/2 function as the first argument and the variable is_bird? is provided manually as second argument.
Compose the steps using pipes
With this in mind, the steps to determine the number of brown birds can be composed with pipes.
animals
|> Enum.filter(is_bird?)
|> Enum.filter(is_brown?)
|> length()
|> then(fn number_of_brown_birds -> "Number of brown birds: #{number_of_brown_birds}" end)
Compose with pipes
Pipes are a great tool to compose functions that solve small problems to solve bigger problems while keeping the code clean and easy to understand.
count_brown = fn animals_to_count ->
animals_to_count
|> Enum.filter(is_brown?)
|> length
end
print_count = fn count, category ->
IO.puts("Number of #{category}: #{count}")
end
animals
|> length()
|> print_count.("animals")
animals
|> count_brown.()
|> print_count.("brown animals")
animals
|> Enum.filter(is_bird?)
|> count_brown.()
|> print_count.("brown birds")
animals
|> Enum.reject(is_bird?)
|> count_brown.()
|> print_count.("brown none-birds")