anchor.diff:      {reply, Sz, Cache};
   
   handle_call(purge, _From, Cache) ->
  -    lists:foreach(fun(Key) ->
  -                          remove_item(Key, Cache)
  -                  end, Cache#cache.evict_list),
  -    {reply, ok, Cache#cache{evict_list=[]}};
  +    {reply, ok, Cache#cache{items=#{}, evict_list=[]}};
   
   handle_call(info, _From, Cache) ->
       #cache{size=Max, evict_list=EvictList} = Cache,
  
positive.code: %% @private
  init([Size, Opts]) ->
      EvictFun = proplists:get_value(evict_fun, Opts),
      Items = ets:new(?MODULE, [ordered_set]),
  
      {ok, #cache{size = Size,
                  evict_list = [],
                  items = Items,
                  evict_fun = EvictFun}}.
  
  
  %% @private
  handle_call({add, {Key, _Value} = Entry}, From, Cache) ->
      case ets:lookup(Cache#cache.items, Key) of
          [] ->
              %% add new item
              true = ets:insert(Cache#cache.items, Entry),
              EvictList = push_front(Cache#cache.evict_list, Entry),
              Cache1 = Cache#cache{evict_list=EvictList},
              %% check if the size is not exceeded
              if
                  length(EvictList) > Cache#cache.size ->
                      gen_server:reply(From, true),
                      {noreply, remove_oldest1(Cache1)};
                  true ->
                      {reply, false, Cache1}
              end;
          [{_Key, _Value}] ->
              gen_server:reply(From, false),
              %% add new value
              true = ets:insert(Cache#cache.items, Entry),
              %% move old entry to front
              EvictList = move_front(Cache#cache.evict_list, Entry),
              {noreply, Cache#cache{evict_list=EvictList}}
      end;
  
  
  handle_call({get, Key, Default}, _From, Cache) ->
      case ets:lookup(Cache#cache.items, Key) of
          [] ->
              {reply, Default, Cache};
          [{_Key, Value}=Entry] ->
              EvictList = move_front(Cache#cache.evict_list, Entry),
              {reply, Value, Cache#cache{evict_list=EvictList}}
      end;
  
  handle_call({peek, Key, Default}, _From, Cache) ->
      Ret = case ets:lookup(Cache#cache.items, Key) of
          [] ->  Default;
          [{_Key, Value}] -> Value
      end,
      {reply, Ret, Cache};
  
  handle_call({contains, Key}, _From, Cache) ->
      {reply, ets:member(Cache#cache.items, Key), Cache};
  
  handle_call({contains_or_add, Entry}, From, Cache) ->
      case ets:insert_new(Cache#cache.items, Entry) of
          true ->
              EvictList = push_front(Cache#cache.evict_list, Entry),
              Cache1 = Cache#cache{evict_list=EvictList},
              % check if the size is not exceeded
              if
                  length(EvictList) > Cache#cache.size ->
                      gen_server:reply(From, {false, true}),
                      {noreply, remove_oldest1(Cache1)};
                  true ->
                      {reply, {false, false}, Cache1}
              end;
          false ->
              {reply, {true, false}, Cache}
      end;
  
  
negative.code: -spec contains_or_add(Cache::pid(), Key::term(), Value::term()) ->
      {Exists::boolean(), Evict::boolean()}.
  contains_or_add(Cache, Key, Value) ->
      call(Cache, {contains_or_add, Key, Value}).
  
  %% @doc remove a key from the cache
  -spec remove(Cache::pid(), Key::term()) -> ok.
  