PragDave Fibonacci solution

Great. Many thanks again for that info.

Following a bit further in the course, it appears that the new homework was indeed to implement the cache as a general purpose key/value cache. I’ve tried to make it as understandable as possible for myself. Would be grateful for any feedback, particularly around the lookup functions (/2 and private /3). I wasn’t sure about using the same name for the 3 functions that handle the lookup, because they handle 2 different stages of the lookup. (in other languages I would have used a conditional inside 1 method.) Also I thought that using _value to give an obvious indication of what was being returned would improve readability when scanning the functions in the pipe.

  defmodule KVCacheAgent do

  @me __MODULE__

  ################################### API ######################################

  def start_cache(initial_state) do
    Agent.start_link(fn -> initial_state end, name: @me)
  end

  def stop_cache() do
    Agent.stop(@me)
  end

  def lookup(key, fn_if_not_found) do
    _value = Agent.get(@me, fn state -> state[key] end)
    |> lookup(key, fn_if_not_found)
  end

  ############################### PRIVATE ######################################

  defp lookup(_value = nil, key, fn_if_not_found) do
    update(key, fn_if_not_found.())
    Agent.get(@me, fn state -> state[key] end)
  end

  defp lookup(value, _key, _fn_if_not_found) do
    value
  end

  defp update(key, value) do
    Agent.update(@me, fn state -> Map.put(state, key, value) end )
  end

end

defmodule Fibber do

  def fib(n) do
    KVCacheAgent.start_cache(%{ 0 => 0, 1 => 1 })
    value = KVCacheAgent.lookup(n, cached_fib(n))
    IO.puts("The fibonacci sequence value for #{n} is: #{value}")
    KVCacheAgent.stop_cache()
  end

  defp cached_fib(n) do
    KVCacheAgent.lookup(n, fn -> cached_fib(n-2) + cached_fib(n-1) end)
  end

end