Packages

Pavlov is a BDD library for your Elixir projects, allowing you to write expressive unit tests that tell the story of how your application behaves. The syntax tries to follow RSpec's wherever possible.

Current section

Files

Jump to
pavlov lib utils memoize.ex
Raw

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