You are actually not identifying which aspects of the code you are having trouble with.
-
The code starts with
CachedFib.fib/1which simply invokesCache.run/1- supplying it’s own anonymous function for calculating any desired value withCachedFib.cached_fib/2. What could be a bit more clear here is thatcacheis a process identifier (PID). -
CachedFib.cached_fib/2tries to look up the value but also supplies an alternate function to calculate the requested value (by accessing the two “previous” values from the “cache process”cacheand summing them). Supplying this “backup strategy” function feels weird but is a concession to the agent - agents only hold state - not logic. So any logic has to be supplied externally. The point here is thatCachesimply caches key value pairs - how these key value pairs are generated is up to the client. (Ultimately agents aren’t that useful but in Elixir learning resources they are often used as a first exposure to processes). -
Meanwhile
Cache.run/1simply starts up the agent and stores the initial values forn = 0andn = 1in the agent (to be consistent this initial value should really come fromCacheFib.fib/1asCacheFib.cache_fib/2also supplies the logic for calculating key/value pairs). The second expression hands the passed anonymous functionbodythe agent’s PID (grantingCachedFib.cached_fib/2access to the agent’s state so that it can be accessed and manipulated with the remainingCachefunctions) binding the finalresultof thebodyfunction. The third expression terminates the agent process. The fourth and final expression simply returns theresultgenerated by the second expression. -
The remaining
Cachefunctions concern themselves with looking up previously calculated values or adding new ones as generated by theif_not_foundfunction - i.e.:
fn -> cached_fib(n-2, cache) + cached_fib(n-1, cache) end
-
Cache.set/3creates a new “state” for the agent by taking the map already stored in the agent and adding{n,val}to it. Note the definition ofAgent.get_and_update/3-Cache.set/3will returnvalwhich is only part of the{n,val}pair - i.e. the calculated value. -
Cache.complete_if_not_found/4uses pattern matching across two function clauses (defining one function). The first clause (the first argument value isnil) is invoked when a requested value wasn’t found in the map (stored as state in the agent); the suppliedif_not_foundfunction is invoked to generate the desired value and the result is pipelined intoCache.set/3to update the agent’s state. Note that calculated result will be returned byCache.set/3. The secondcomplete_if_not_found/4function clause simply returns thevalueit was given (from the map stored as the agent state). -
Cache.lookup/3simply tries to look up the requested value. The result drives what happens withCache.complete_if_not_found/4- it either simply returns the looked up value or generates the required value with the suppliedif_not_foundfunction.






















