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