@@ -54,6 +54,13 @@ defmodule HashDict do
5454 contract_on: @ contract_load ,
5555 root: @ node_template
5656
57+
58+ @ typep ordered :: { HashDict , size :: non_neg_integer , [ { key :: term , value :: term } ] }
59+ @ typep trie :: { HashDict , size :: non_neg_integer , depth :: non_neg_integer ,
60+ expand_on :: non_neg_integer , contract_on :: non_neg_integer ,
61+ root :: tuple }
62+ @ opaque t :: ordered | trie
63+
5764 import Bitwise
5865
5966 # Let's inline common instructions
@@ -62,6 +69,7 @@ defmodule HashDict do
6269 @ doc """
6370 Creates a new empty dict.
6471 """
72+ @ spec new :: t
6573 def new do
6674 ordered ( )
6775 end
@@ -75,6 +83,7 @@ defmodule HashDict do
7583 #=> HashDict[a: 1, b: 2]
7684
7785 """
86+ @ spec new ( [ { term :: term , value :: term } ] ) :: t
7887 def new ( pairs ) do
7988 Enum . reduce pairs , ordered ( ) , fn { k , v } , dict ->
8089 put ( dict , k , v )
@@ -91,6 +100,7 @@ defmodule HashDict do
91100 #=> HashDict[{ "a", "a" }, { "b", "b" }]
92101
93102 """
103+ @ spec new ( list , ( term -> { key :: term , key :: term } ) ) :: t
94104 def new ( list , transform ) when is_function ( transform ) do
95105 Enum . reduce list , new ( ) , fn i , dict ->
96106 { k , v } = transform . ( i )
@@ -101,6 +111,7 @@ defmodule HashDict do
101111 @ doc """
102112 Puts the given key and value in the dict.
103113 """
114+ @ spec put ( t , key :: term , value :: term ) :: t
104115 def put ( dict , key , value ) do
105116 { dict , _ } = dict_put ( dict , key , { :put , value } )
106117 dict
@@ -110,6 +121,7 @@ defmodule HashDict do
110121 Puts the given value under key in the dictionary
111122 only if one does not exist yet.
112123 """
124+ @ spec put_new ( t , key :: term , value :: term ) :: t
113125 def put_new ( dict , key , value ) do
114126 update ( dict , key , value , fn ( v ) -> v end )
115127 end
@@ -119,6 +131,7 @@ defmodule HashDict do
119131 to the given function. Raises if the key does
120132 not exist in the dictionary.
121133 """
134+ @ spec update ( t , key :: term , ( term -> term ) ) :: t
122135 def update ( dict , key , fun ) when is_function ( fun , 1 ) do
123136 case dict_put ( dict , key , { :update , nil , fun } ) do
124137 { dict , 0 } ->
@@ -133,6 +146,7 @@ defmodule HashDict do
133146 to the given function. Adds initial value if
134147 the key does not exist in the dicionary.
135148 """
149+ @ spec update ( t , key :: term , initial :: term , ( term -> term ) ) :: t
136150 def update ( dict , key , initial , fun ) when is_function ( fun , 1 ) do
137151 { dict , _ } = dict_put ( dict , key , { :update , initial , fun } )
138152 dict
@@ -141,6 +155,8 @@ defmodule HashDict do
141155 @ doc """
142156 Gets the value under key from the dict.
143157 """
158+ @ spec get ( t , key :: term ) :: term
159+ @ spec get ( t , key :: term , default :: term ) :: term
144160 def get ( dict , key , default // nil ) do
145161 case dict_get ( dict , key ) do
146162 { ^ key , value } -> value
@@ -152,6 +168,7 @@ defmodule HashDict do
152168 Gets the value under key from the dict,
153169 raises KeyError if such key does not exist.
154170 """
171+ @ spec get! ( t , key :: term ) :: term | no_return
155172 def get! ( dict , key ) when is_tuple ( dict ) do
156173 case dict_get ( dict , key ) do
157174 { ^ key , value } -> value
@@ -162,13 +179,15 @@ defmodule HashDict do
162179 @ doc """
163180 Checks if the dict has the given key.
164181 """
182+ @ spec has_key? ( t , key :: term ) :: boolean
165183 def has_key? ( dict , key ) do
166184 match? { ^ key , _ } , dict_get ( dict , key )
167185 end
168186
169187 @ doc """
170188 Deletes a value from the dict.
171189 """
190+ @ spec delete ( t , key :: term ) :: t
172191 def delete ( ordered ( bucket: bucket , size: size ) = dict , key ) do
173192 case bucket_delete ( bucket , key ) do
174193 { _ , 0 } ->
@@ -201,20 +220,23 @@ defmodule HashDict do
201220 @ doc """
202221 Returns the dict size.
203222 """
223+ @ spec size ( t ) :: non_neg_integer
204224 def size ( dict ) do
205225 elem ( dict , 1 )
206226 end
207227
208228 @ doc """
209229 Returns an empty dict.
210230 """
231+ @ spec empty ( t ) :: t
211232 def empty ( _ ) do
212233 ordered ( )
213234 end
214235
215236 @ doc """
216237 Converts the dict to a list.
217238 """
239+ @ spec to_list ( t ) :: list ( { key :: term , value :: term } )
218240 def to_list ( ordered ( bucket: bucket ) ) do
219241 bucket
220242 end
@@ -226,20 +248,24 @@ defmodule HashDict do
226248 @ doc """
227249 Get all keys in the dict.
228250 """
251+ @ spec keys ( t ) :: list ( key :: term )
229252 def keys ( dict ) do
230253 dict_fold ( dict , [ ] , fn { k , _ } , acc -> [ k | acc ] end )
231254 end
232255
233256 @ doc """
234257 Get all values in the dict.
235258 """
259+ @ spec values ( t ) :: list ( values :: term )
236260 def values ( dict ) do
237261 dict_fold ( dict , [ ] , fn { _ , v } , acc -> [ v | acc ] end )
238262 end
239263
240264 @ doc """
241265 Merges two dictionaries.
242266 """
267+ @ spec merge ( t , t | Dict . t ) :: t
268+ @ spec merge ( t , t | Dict . t , ( ( key :: term , value1 :: term , value2 :: term ) -> value :: term ) ) :: t
243269 def merge ( dict , enum , callback // fn ( _k , _v1 , v2 ) -> v2 end )
244270
245271 def merge ( dict1 , dict2 , callback ) when is_record ( dict1 , HashDict ) and is_record ( dict2 , HashDict ) and elem ( dict1 , 1 ) < elem ( dict2 , 1 ) do
0 commit comments