Skip to content

Instantly share code, notes, and snippets.

@josevalim
Forked from sasa1977/dict.behaviour.ex
Last active December 20, 2015 19:18
Show Gist options
  • Save josevalim/6181949 to your computer and use it in GitHub Desktop.
Save josevalim/6181949 to your computer and use it in GitHub Desktop.
defmodule Dict.Behaviour do
# It is assumed that the client module implements following functions:
#
# size/1, fetch/2, put/3, reduce/3, update/4, delete/2
#
defmacro __using__(_) do
quote do
# Following are exact copies of HashDict:
def get(dict, key, default // nil) do
case fetch(dict, key) do
{ :ok, value } -> value
:error -> default
end
end
def has_key?(dict, key) do
match? { :ok, _ }, fetch(dict, key)
end
def put_new(dict, key, value) do
update(dict, key, value, fn(v) -> v end)
end
def drop(dict, []), do: dict
def drop(dict, [key|keys]) do
drop(delete(dict, key), keys)
end
def take(dict, keys) do
take(dict, keys, new)
end
defp take(_dict, [], acc), do: acc
defp take(dict, [key|keys], acc) do
case fetch(dict, key) do
{ :ok, value } -> take(dict, keys, put(acc, key, value))
:error -> take(dict, keys, acc)
end
end
# end of exact copies
# Almost the same, but without the guard 'when is_tuple(dict)'
def fetch!(dict, key) do
case fetch(dict, key) do
{ :ok, value } -> value
:error -> raise(KeyError, key: key)
end
end
def to_list(dict), do: reduce(dict, [], &[&1|&2]) |> Enum.reverse
def keys(dict), do: reduce(dict, [], fn({k, _}, acc) -> [k | acc] end) |> Enum.reverse
def values(dict), do: reduce(dict, [], fn({_, v}, acc) -> [v | acc] end) |> Enum.reverse
# Very similar implementation, but relies on Enum
def equal?(dict1, dict2) do
case size(dict1) == size(dict2) do
false -> false
true ->
try do
reduce(dict1, nil, fn({ k, v }, _acc) ->
unless fetch(dict2, k) == { :ok, v }, do: throw(:error)
end)
true
catch
:error -> false
end
end
end
# Radically different implementation. I'm not sure about the speed.
def merge(dict, enumerable, callback // fn(_k, _v1, v2) -> v2 end) do
reduce(enumerable, dict, fn({key, value}, acc) ->
update(acc, key, value, fn(v1) -> callback(key, v1, value) end)
end)
end
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment