-module(immutable_lru). -compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]). -export([new/1, get/2, get_exn/2, set/3, has/2, clear/1]). -export_type([lru_cache/2]). -opaque lru_cache(FWG, FWH) :: {lru_cache, gleam@dict:dict(FWG, FWH), gleam@dict:dict(FWG, FWH), integer(), integer()}. -spec new(integer()) -> lru_cache(any(), any()). new(Max) -> Active = gleam@dict:new(), Stale = gleam@dict:new(), {lru_cache, Active, Stale, Max, 0}. -spec keep(lru_cache(FXA, FXB), FXA, FXB) -> lru_cache(FXA, FXB). keep(Cache, Key, Value) -> Key_count = erlang:element(5, Cache) + 1, {Active, Stale, Key_count@1} = case Key_count > erlang:element(4, Cache) of true -> {gleam@dict:new(), erlang:element(2, Cache), 1}; false -> {erlang:element(2, Cache), erlang:element(3, Cache), Key_count} end, Active@1 = gleam@dict:insert(Active, Key, Value), erlang:setelement( 5, erlang:setelement(3, erlang:setelement(2, Cache, Active@1), Stale), Key_count@1 ). -spec get(lru_cache(FWM, FWN), FWM) -> {ok, {lru_cache(FWM, FWN), FWN}} | {error, nil}. get(Cache, Key) -> _pipe = erlang:element(2, Cache), _pipe@1 = gleam@dict:get(_pipe, Key), _pipe@2 = gleam@result:map(_pipe@1, fun(Val) -> {Cache, Val} end), gleam@result:lazy_or(_pipe@2, fun() -> _pipe@3 = erlang:element(3, Cache), _pipe@4 = gleam@dict:get(_pipe@3, Key), gleam@result:map( _pipe@4, fun(Val@1) -> {keep(Cache, Key, Val@1), Val@1} end ) end). -spec get_exn(lru_cache(FWU, FWV), FWU) -> {lru_cache(FWU, FWV), FWV}. get_exn(C, Key) -> case get(C, Key) of {ok, Pair} -> Pair; _ -> erlang:error(#{gleam_error => panic, message => <<"key not found in cache"/utf8>>, module => <<"immutable_lru"/utf8>>, function => <<"get_exn"/utf8>>, line => 103}) end. -spec set(lru_cache(FXG, FXH), FXG, FXH) -> lru_cache(FXG, FXH). set(Cache, Key, Value) -> case gleam@dict:has_key(erlang:element(2, Cache), Key) of true -> Active = gleam@dict:insert(erlang:element(2, Cache), Key, Value), erlang:setelement(2, Cache, Active); false -> keep(Cache, Key, Value) end. -spec has(lru_cache(FXM, any()), FXM) -> boolean(). has(Cache, Key) -> _pipe = erlang:element(2, Cache), _pipe@1 = gleam@dict:get(_pipe, Key), _pipe@3 = gleam@result:lazy_or( _pipe@1, fun() -> _pipe@2 = erlang:element(3, Cache), gleam@dict:get(_pipe@2, Key) end ), gleam@result:is_ok(_pipe@3). -spec clear(lru_cache(FXQ, FXR)) -> lru_cache(FXQ, FXR). clear(Cache) -> new(erlang:element(4, Cache)).