 
   # Get the neighboring positions of `position`, filter out the dead neighbors,
   # then get the cell positions which should be created and return them.
+  @spec to_create(position) :: [position]
   defp to_create(position) do
     position
     |> get_neighboring_positions

  # Get the living neighbors of `position`.  If there are exactly 2 or 3, this `position`
  # lives, otherwise it will be destroyed.
  # Returns itself if it should be destroyed, otherwise returns an empty list.
  defp to_destroy(position) do
    position
    |> count_living_neighbors

  end

  # Get all `{x, y}` coordinates of neighboring cells based on the input `{x, y}` and return them.
  @spec get_neighboring_positions(position) :: [position]
  defp get_neighboring_positions({x, y}) do
     @neighbor_offsets
     |> map(fn {dx, dy} -> {x + dx, y + dy} end)
  end

  # Filter out the `positions` which are not currently alive and return them.
  @spec get_dead_neighbors([position]) :: [position]
  defp get_dead_neighbors(positions) do
    filter(positions, &(lookup(&1) == nil))
  end
