Current section
Files
Jump to
Current section
Files
lib/utils/memoize.ex
defmodule Pavlov.Utils.Memoize do
@moduledoc false
alias Pavlov.Utils.Memoize.ResultTable
defmacro defmem(header, do: body) do
{ name, _meta, vars } = header
quote do
def unquote(header) do
case ResultTable.get(unquote(name), unquote(vars)) do
{ :hit, result } -> result
:miss ->
result = unquote(body)
ResultTable.put(unquote(name), unquote(vars), result)
result
end
end
end
end
# gen_server keeping results for function calls
defmodule ResultTable do
@moduledoc false
use GenServer
def start_link do
GenServer.start_link(__MODULE__, HashDict.new, name: :result_table)
end
def handle_call({ :get, fun, args }, _sender, dict) do
if Dict.has_key?(dict, { fun, args }) do
{ :reply, { :hit, dict[{ fun, args }] }, dict }
else
{ :reply, :miss, dict }
end
end
def handle_cast({ :put, fun, args, result }, dict) do
{ :noreply, Dict.put(dict, { fun, args }, result) }
end
def get(fun, args), do: GenServer.call(:result_table, { :get, fun, args })
def put(fun, args, result), do: GenServer.cast(:result_table, { :put, fun, args, result })
end
end