diff --git a/lib/elixir/lib/dict.ex b/lib/elixir/lib/dict.ex index 3b2ffce0670..b540ef1786b 100644 --- a/lib/elixir/lib/dict.ex +++ b/lib/elixir/lib/dict.ex @@ -13,7 +13,6 @@ defmodule Dict do @type value :: any @type t :: list | map - # TODO: Deprecate every function by 1.4 defmacro __using__(_) do # Use this import to guarantee proper code expansion import Kernel, except: [size: 1] @@ -22,7 +21,18 @@ defmodule Dict do :elixir_errors.warn(line, file, "the Dict module is deprecated") quote do + defmacrop __dict_warn_deprecated__() do + quote do + {function, arity} = __ENV__.function + IO.warn String.trim_trailing(""" + #{inspect(__MODULE__)}.#{function}/#{arity} has been generated by a + call to "use Dict", and the Dict module has been deprecated + """) + end + end + def get(dict, key, default \\ nil) do + __dict_warn_deprecated__() case fetch(dict, key) do {:ok, value} -> value :error -> default @@ -30,6 +40,7 @@ defmodule Dict do end def get_lazy(dict, key, fun) when is_function(fun, 0) do + __dict_warn_deprecated__() case fetch(dict, key) do {:ok, value} -> value :error -> fun.() @@ -37,12 +48,14 @@ defmodule Dict do end def get_and_update(dict, key, fun) do + __dict_warn_deprecated__() current_value = get(dict, key) {get, new_value} = fun.(current_value) {get, put(dict, key, new_value)} end def fetch!(dict, key) do + __dict_warn_deprecated__() case fetch(dict, key) do {:ok, value} -> value :error -> raise KeyError, key: key, term: dict @@ -50,10 +63,12 @@ defmodule Dict do end def has_key?(dict, key) do + __dict_warn_deprecated__() match? {:ok, _}, fetch(dict, key) end def put_new(dict, key, value) do + __dict_warn_deprecated__() case has_key?(dict, key) do true -> dict false -> put(dict, key, value) @@ -61,6 +76,7 @@ defmodule Dict do end def put_new_lazy(dict, key, fun) when is_function(fun, 0) do + __dict_warn_deprecated__() case has_key?(dict, key) do true -> dict false -> put(dict, key, fun.()) @@ -68,10 +84,12 @@ defmodule Dict do end def drop(dict, keys) do + __dict_warn_deprecated__() Enum.reduce(keys, dict, &delete(&2, &1)) end def take(dict, keys) do + __dict_warn_deprecated__() Enum.reduce(keys, new(), fn key, acc -> case fetch(dict, key) do {:ok, value} -> put(acc, key, value) @@ -81,24 +99,28 @@ defmodule Dict do end def to_list(dict) do + __dict_warn_deprecated__() reduce(dict, {:cont, []}, fn kv, acc -> {:cont, [kv | acc]} end) |> elem(1) |> :lists.reverse end def keys(dict) do + __dict_warn_deprecated__() reduce(dict, {:cont, []}, fn {k, _}, acc -> {:cont, [k | acc]} end) |> elem(1) |> :lists.reverse end def values(dict) do + __dict_warn_deprecated__() reduce(dict, {:cont, []}, fn {_, v}, acc -> {:cont, [v | acc]} end) |> elem(1) |> :lists.reverse end def equal?(dict1, dict2) do + __dict_warn_deprecated__() # Use this import to avoid conflicts in the user code import Kernel, except: [size: 1] @@ -115,6 +137,7 @@ defmodule Dict do end def merge(dict1, dict2, fun \\ fn(_k, _v1, v2) -> v2 end) do + __dict_warn_deprecated__() # Use this import to avoid conflicts in the user code import Kernel, except: [size: 1] @@ -130,6 +153,7 @@ defmodule Dict do end def update(dict, key, initial, fun) do + __dict_warn_deprecated__() case fetch(dict, key) do {:ok, value} -> put(dict, key, fun.(value)) @@ -139,6 +163,7 @@ defmodule Dict do end def update!(dict, key, fun) do + __dict_warn_deprecated__() case fetch(dict, key) do {:ok, value} -> put(dict, key, fun.(value)) @@ -148,6 +173,7 @@ defmodule Dict do end def pop(dict, key, default \\ nil) do + __dict_warn_deprecated__() case fetch(dict, key) do {:ok, value} -> {value, delete(dict, key)} @@ -157,6 +183,7 @@ defmodule Dict do end def pop_lazy(dict, key, fun) when is_function(fun, 0) do + __dict_warn_deprecated__() case fetch(dict, key) do {:ok, value} -> {value, delete(dict, key)} @@ -166,6 +193,7 @@ defmodule Dict do end def split(dict, keys) do + __dict_warn_deprecated__() Enum.reduce(keys, {new(), dict}, fn key, {inc, exc} = acc -> case fetch(exc, key) do {:ok, value} -> @@ -199,73 +227,98 @@ defmodule Dict do end end + defmacrop warn_deprecated() do + quote do + {function, arity} = __ENV__.function + IO.warn String.trim_trailing(""" + Dict.#{function}/#{arity} is deprecated since the Dict module is + deprecated; use the Map module for working with maps or the Keyword + module for working with keyword lists + """) + end + end + @spec keys(t) :: [key] def keys(dict) do + warn_deprecated() target(dict).keys(dict) end @spec values(t) :: [value] def values(dict) do + warn_deprecated() target(dict).values(dict) end @spec size(t) :: non_neg_integer def size(dict) do + warn_deprecated() target(dict).size(dict) end @spec has_key?(t, key) :: boolean def has_key?(dict, key) do + warn_deprecated() target(dict).has_key?(dict, key) end @spec get(t, key, value) :: value def get(dict, key, default \\ nil) do + warn_deprecated() target(dict).get(dict, key, default) end @spec get_lazy(t, key, (() -> value)) :: value def get_lazy(dict, key, fun) do + warn_deprecated() target(dict).get_lazy(dict, key, fun) end @spec get_and_update(t, key, (value -> {value, value})) :: {value, t} def get_and_update(dict, key, fun) do + warn_deprecated() target(dict).get_and_update(dict, key, fun) end @spec fetch(t, key) :: value def fetch(dict, key) do + warn_deprecated() target(dict).fetch(dict, key) end @spec fetch!(t, key) :: value | no_return def fetch!(dict, key) do + warn_deprecated() target(dict).fetch!(dict, key) end @spec put(t, key, value) :: t def put(dict, key, val) do + warn_deprecated() target(dict).put(dict, key, val) end @spec put_new(t, key, value) :: t def put_new(dict, key, val) do + warn_deprecated() target(dict).put_new(dict, key, val) end @spec put_new_lazy(t, key, (() -> value)) :: t def put_new_lazy(dict, key, fun) do + warn_deprecated() target(dict).put_new_lazy(dict, key, fun) end @spec delete(t, key) :: t def delete(dict, key) do + warn_deprecated() target(dict).delete(dict, key) end @spec merge(t, t) :: t def merge(dict1, dict2) do + warn_deprecated() target1 = target(dict1) target2 = target(dict2) @@ -278,6 +331,7 @@ defmodule Dict do @spec merge(t, t, (key, value, value -> value)) :: t def merge(dict1, dict2, fun) do + warn_deprecated() target1 = target(dict1) target2 = target(dict2) @@ -296,46 +350,55 @@ defmodule Dict do @spec pop(t, key, value) :: {value, t} def pop(dict, key, default \\ nil) do + warn_deprecated() target(dict).pop(dict, key, default) end @spec pop_lazy(t, key, (() -> value)) :: {value, t} def pop_lazy(dict, key, fun) do + warn_deprecated() target(dict).pop_lazy(dict, key, fun) end @spec update!(t, key, (value -> value)) :: t def update!(dict, key, fun) do + warn_deprecated() target(dict).update!(dict, key, fun) end @spec update(t, key, value, (value -> value)) :: t def update(dict, key, initial, fun) do + warn_deprecated() target(dict).update(dict, key, initial, fun) end @spec split(t, [key]) :: {t, t} def split(dict, keys) do + warn_deprecated() target(dict).split(dict, keys) end @spec drop(t, [key]) :: t def drop(dict, keys) do + warn_deprecated() target(dict).drop(dict, keys) end @spec take(t, [key]) :: t def take(dict, keys) do + warn_deprecated() target(dict).take(dict, keys) end @spec empty(t) :: t def empty(dict) do + warn_deprecated() target(dict).empty(dict) end @spec equal?(t, t) :: boolean def equal?(dict1, dict2) do + warn_deprecated() target1 = target(dict1) target2 = target(dict2) @@ -358,6 +421,7 @@ defmodule Dict do @spec to_list(t) :: list def to_list(dict) do + warn_deprecated() target(dict).to_list(dict) end diff --git a/lib/elixir/lib/hash_dict.ex b/lib/elixir/lib/hash_dict.ex index 14b7ac14aa7..c9310a859aa 100644 --- a/lib/elixir/lib/hash_dict.ex +++ b/lib/elixir/lib/hash_dict.ex @@ -5,8 +5,6 @@ defmodule HashDict do Use the `Map` module instead. """ - # TODO: Deprecate every function by 1.4 - use Dict @node_bitmap 0b111 @@ -22,35 +20,51 @@ defmodule HashDict do @compile :inline_list_funcs @compile {:inline, key_hash: 1, key_mask: 1, key_shift: 1} + defmacrop warn_deprecated() do + quote do + {function, arity} = __ENV__.function + IO.warn String.trim_trailing(""" + HashDict.#{function}/#{arity} is deprecated since the HashDict module is + deprecated; use maps and the Map module instead + """) + end + end + @doc """ Creates a new empty dict. """ @spec new :: Dict.t def new do + warn_deprecated() %HashDict{} end def put(%HashDict{root: root, size: size}, key, value) do + warn_deprecated() {root, counter} = do_put(root, key, value, key_hash(key)) %HashDict{root: root, size: size + counter} end def update!(%HashDict{root: root, size: size} = dict, key, fun) when is_function(fun, 1) do + warn_deprecated() {root, counter} = do_update(root, key, fn -> raise KeyError, key: key, term: dict end, fun, key_hash(key)) %HashDict{root: root, size: size + counter} end def update(%HashDict{root: root, size: size}, key, initial, fun) when is_function(fun, 1) do + warn_deprecated() {root, counter} = do_update(root, key, fn -> initial end, fun, key_hash(key)) %HashDict{root: root, size: size + counter} end def fetch(%HashDict{root: root}, key) do + warn_deprecated() do_fetch(root, key, key_hash(key)) end def delete(dict, key) do + warn_deprecated() case dict_delete(dict, key) do {dict, _value} -> dict :error -> dict @@ -58,6 +72,7 @@ defmodule HashDict do end def pop(dict, key, default \\ nil) do + warn_deprecated() case dict_delete(dict, key) do {dict, value} -> {value, dict} :error -> {default, dict} @@ -65,6 +80,7 @@ defmodule HashDict do end def size(%HashDict{size: size}) do + warn_deprecated() size end diff --git a/lib/elixir/lib/hash_set.ex b/lib/elixir/lib/hash_set.ex index 554b30c2d3d..dfefed765cb 100644 --- a/lib/elixir/lib/hash_set.ex +++ b/lib/elixir/lib/hash_set.ex @@ -5,8 +5,6 @@ defmodule HashSet do Use the `MapSet` module instead. """ - # TODO: Deprecate every function by 1.4 - @node_bitmap 0b111 @node_shift 3 @node_size 8 @@ -20,34 +18,51 @@ defmodule HashSet do @compile :inline_list_funcs @compile {:inline, key_hash: 1, key_mask: 1, key_shift: 1} + defmacrop warn_deprecated() do + quote do + {function, arity} = __ENV__.function + IO.warn String.trim_trailing(""" + HashSet.#{function}/#{arity} is deprecated since the HashSet module is + deprecated; use the MapSet module instead + """) + end + end + @spec new :: Set.t def new do + warn_deprecated() %HashSet{} end def union(%HashSet{size: size1} = set1, %HashSet{size: size2} = set2) when size1 <= size2 do + warn_deprecated() set_fold set1, set2, fn v, acc -> put(acc, v) end end def union(%HashSet{} = set1, %HashSet{} = set2) do + warn_deprecated() set_fold set2, set1, fn v, acc -> put(acc, v) end end def intersection(%HashSet{} = set1, %HashSet{} = set2) do + warn_deprecated() set_fold set1, %HashSet{}, fn v, acc -> if member?(set2, v), do: put(acc, v), else: acc end end def difference(%HashSet{} = set1, %HashSet{} = set2) do + warn_deprecated() set_fold set2, set1, fn v, acc -> delete(acc, v) end end def to_list(set) do + warn_deprecated() set_fold(set, [], &[&1 | &2]) |> :lists.reverse end def equal?(%HashSet{size: size1} = set1, %HashSet{size: size2} = set2) do + warn_deprecated() case size1 do ^size2 -> subset?(set1, set2) _ -> false @@ -55,6 +70,7 @@ defmodule HashSet do end def subset?(%HashSet{} = set1, %HashSet{} = set2) do + warn_deprecated() reduce(set1, {:cont, true}, fn member, acc -> case member?(set2, member) do true -> {:cont, acc} @@ -64,6 +80,7 @@ defmodule HashSet do end def disjoint?(%HashSet{} = set1, %HashSet{} = set2) do + warn_deprecated() reduce(set2, {:cont, true}, fn member, acc -> case member?(set1, member) do false -> {:cont, acc} @@ -73,15 +90,18 @@ defmodule HashSet do end def member?(%HashSet{root: root}, term) do + warn_deprecated() do_member?(root, term, key_hash(term)) end def put(%HashSet{root: root, size: size}, term) do + warn_deprecated() {root, counter} = do_put(root, term, key_hash(term)) %HashSet{root: root, size: size + counter} end def delete(%HashSet{root: root, size: size} = set, term) do + warn_deprecated() case do_delete(root, term, key_hash(term)) do {:ok, root} -> %HashSet{root: root, size: size - 1} :error -> set @@ -98,6 +118,7 @@ defmodule HashSet do end def size(%HashSet{size: size}) do + warn_deprecated() size end