Packages

Simple memoization for Gleam (Erlang target)

Current section

Files

Jump to
rememo_erlang src rememo@memo.erl
Raw

src/rememo@memo.erl

-module(rememo@memo).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]).
-define(FILEPATH, "src/rememo/memo.gleam").
-export([create/1, set/3, get/2, memoize/3]).
-if(?OTP_RELEASE >= 27).
-define(MODULEDOC(Str), -moduledoc(Str)).
-define(DOC(Str), -doc(Str)).
-else.
-define(MODULEDOC(Str), -compile([])).
-define(DOC(Str), -compile([])).
-endif.
?MODULEDOC(" The cache is a [Erlang Term Storage database](https://www.erlang.org/doc/apps/erts/persistent_term.html).\n").
-file("src/rememo/memo.gleam", 20).
?DOC(
" Make a new memoization cache that will be used for the rest of the inner scope\n"
" of the provided function.\n"
" Pass this cache to the function you want to memoize.\n"
" \n"
" This is best used with a `use` expression:\n"
" ```gleam\n"
" use cache <- create()\n"
" f(a, b, c, cache)\n"
" ```\n"
).
-spec create(fun((internal@carpenter@table:set(any(), any())) -> IDL)) -> IDL.
create(Fun) ->
Table_name = begin
_pipe = tempo@instant:now(),
gleam@string:inspect(_pipe)
end,
Cache_table@1 = case begin
_pipe@1 = internal@carpenter@table:build(Table_name),
_pipe@2 = internal@carpenter@table:privacy(_pipe@1, private),
_pipe@3 = internal@carpenter@table:write_concurrency(
_pipe@2,
auto_write_concurrency
),
_pipe@4 = internal@carpenter@table:read_concurrency(_pipe@3, true),
_pipe@5 = internal@carpenter@table:decentralized_counters(_pipe@4, true),
_pipe@6 = internal@carpenter@table:compression(_pipe@5, false),
internal@carpenter@table:set(_pipe@6)
end of
{ok, Cache_table} -> Cache_table;
_assert_fail ->
erlang:error(#{gleam_error => let_assert,
message => <<"Pattern match failed, no pattern matched the value."/utf8>>,
file => <<?FILEPATH/utf8>>,
module => <<"rememo/memo"/utf8>>,
function => <<"create"/utf8>>,
line => 23,
value => _assert_fail,
start => 659,
'end' => 927,
pattern_start => 670,
pattern_end => 685})
end,
Result = Fun(Cache_table@1),
internal@carpenter@table:drop(Cache_table@1),
Result.
-file("src/rememo/memo.gleam", 39).
?DOC(
" Manually add a key-value pair to the memoization cache.\n"
" Useful if you need to pre-seed the cache with a starting value, for example.\n"
).
-spec set(internal@carpenter@table:set(IDN, IDO), IDN, IDO) -> nil.
set(Cache, Key, Value) ->
internal@carpenter@table:insert(Cache, [{Key, Value}]).
-file("src/rememo/memo.gleam", 45).
?DOC(
" Manually look up a value from the memoization cache for a given key.\n"
" Useful if you want to also return intermediate results as well as a final result, for example.\n"
).
-spec get(internal@carpenter@table:set(IDR, IDS), IDR) -> {ok, IDS} |
{error, nil}.
get(Cache, Key) ->
case internal@carpenter@table:lookup(Cache, Key) of
[] ->
{error, nil};
[{_, V} | _] ->
{ok, V}
end.
-file("src/rememo/memo.gleam", 65).
?DOC(
" Look up the value associated with the given key in the memoization cache,\n"
" and return it if it exists. If it doesn't exist, evaluate the callback function\n"
" update the cache with the key and the corresponding value the callback returned, \n"
" and return that value.\n"
" \n"
" This works well with a `use` expression:\n"
" ```gleam\n"
" fn f(a, b, c, cache) {\n"
" use <- memoize(cache, #(a, b, c))\n"
" // function body goes here\n"
" }\n"
" ```\n"
).
-spec memoize(internal@carpenter@table:set(IDX, IDY), IDX, fun(() -> IDY)) -> IDY.
memoize(Cache, Key, Fun) ->
case get(Cache, Key) of
{ok, Value} ->
Value;
{error, nil} ->
Result = Fun(),
set(Cache, Key, Result),
Result
end.