Contents

Higher order functions

A higher order function is a one that takes as input or (returns as output) another function. Here, we will have a look at three of the most widely used higher order functions, namely fold (a.k.a. reduce), map and filter.

Map

The map function takes two parameters as input, i.e. a list and a function, and produces a new list. The elements in the output list correspond to the result of applying the input function on every element in the input list. The following snippet illustrates to the implementation of the map function.

defmodule MList do
  def map([], _fun), do: []
  def map([head|tail], fun), do: [fun.(head) | map(tail, fun)]
end

Fold

On the other hand, the fold function takes as input a list, an initial value and a function, and applies the function to all the elements of the list and the initial value pairwise to produce a single result. There are two variants of the fold operation referred to as foldl (fold from left) and foldr (fold from right), which traverse the list in one direction or the other. The implementation of both variants is shown below:

defmodule MList do
  def foldl([], acc, _fun), do: acc
  def foldl([head|tail], acc, fun), do: foldl(tail, fun.(head, acc), fun)
  def foldr([], acc, _fun), do: acc
  def foldr([head|tail], acc, fun), do: fun.(head, foldr(tail, acc, fun))
end

Filter

Finally, as the name itself hints, the filter function takes as input a list and a function and produces a new list, keeping only the elements for which the input function returns true. The snippet below shows the implementation of this function.

defmodule MList do
  def filter([], _fun), do: []
  def filter([head|tail], fun) do
    case fun.(head) do
        true -> [head | filter(tail, fun)]
        _ -> filter(tail, fun)
    end
  end
end

Binary tree

As part of this lecture, we started with the implementation of the well-known binary tree data structure. The snippet below includes the code for building the binary tree. It is now your turn to implement the tree traversals.

defmodule BinaryTree do
  def insert(nil, value), do: {value, nil, nil}

  def insert({value, left, right}, new_value) when new_value < value do
    {value, insert(left, new_value), right}
  end

  def insert({value, left, right}, new_value) do
    {value, left, insert(right, new_value)}
  end
  ...
end