@@ -54,6 +54,13 @@ defmodule HashDict do
54
54
contract_on: @ contract_load ,
55
55
root: @ node_template
56
56
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
+
57
64
import Bitwise
58
65
59
66
# Let's inline common instructions
@@ -62,6 +69,7 @@ defmodule HashDict do
62
69
@ doc """
63
70
Creates a new empty dict.
64
71
"""
72
+ @ spec new :: t
65
73
def new do
66
74
ordered ( )
67
75
end
@@ -75,6 +83,7 @@ defmodule HashDict do
75
83
#=> HashDict[a: 1, b: 2]
76
84
77
85
"""
86
+ @ spec new ( [ { term :: term , value :: term } ] ) :: t
78
87
def new ( pairs ) do
79
88
Enum . reduce pairs , ordered ( ) , fn { k , v } , dict ->
80
89
put ( dict , k , v )
@@ -91,6 +100,7 @@ defmodule HashDict do
91
100
#=> HashDict[{ "a", "a" }, { "b", "b" }]
92
101
93
102
"""
103
+ @ spec new ( list , ( term -> { key :: term , key :: term } ) ) :: t
94
104
def new ( list , transform ) when is_function ( transform ) do
95
105
Enum . reduce list , new ( ) , fn i , dict ->
96
106
{ k , v } = transform . ( i )
@@ -101,6 +111,7 @@ defmodule HashDict do
101
111
@ doc """
102
112
Puts the given key and value in the dict.
103
113
"""
114
+ @ spec put ( t , key :: term , value :: term ) :: t
104
115
def put ( dict , key , value ) do
105
116
{ dict , _ } = dict_put ( dict , key , { :put , value } )
106
117
dict
@@ -110,6 +121,7 @@ defmodule HashDict do
110
121
Puts the given value under key in the dictionary
111
122
only if one does not exist yet.
112
123
"""
124
+ @ spec put_new ( t , key :: term , value :: term ) :: t
113
125
def put_new ( dict , key , value ) do
114
126
update ( dict , key , value , fn ( v ) -> v end )
115
127
end
@@ -119,6 +131,7 @@ defmodule HashDict do
119
131
to the given function. Raises if the key does
120
132
not exist in the dictionary.
121
133
"""
134
+ @ spec update ( t , key :: term , ( term -> term ) ) :: t
122
135
def update ( dict , key , fun ) when is_function ( fun , 1 ) do
123
136
case dict_put ( dict , key , { :update , nil , fun } ) do
124
137
{ dict , 0 } ->
@@ -133,6 +146,7 @@ defmodule HashDict do
133
146
to the given function. Adds initial value if
134
147
the key does not exist in the dicionary.
135
148
"""
149
+ @ spec update ( t , key :: term , initial :: term , ( term -> term ) ) :: t
136
150
def update ( dict , key , initial , fun ) when is_function ( fun , 1 ) do
137
151
{ dict , _ } = dict_put ( dict , key , { :update , initial , fun } )
138
152
dict
@@ -141,6 +155,8 @@ defmodule HashDict do
141
155
@ doc """
142
156
Gets the value under key from the dict.
143
157
"""
158
+ @ spec get ( t , key :: term ) :: term
159
+ @ spec get ( t , key :: term , default :: term ) :: term
144
160
def get ( dict , key , default // nil ) do
145
161
case dict_get ( dict , key ) do
146
162
{ ^ key , value } -> value
@@ -152,6 +168,7 @@ defmodule HashDict do
152
168
Gets the value under key from the dict,
153
169
raises KeyError if such key does not exist.
154
170
"""
171
+ @ spec get! ( t , key :: term ) :: term | no_return
155
172
def get! ( dict , key ) when is_tuple ( dict ) do
156
173
case dict_get ( dict , key ) do
157
174
{ ^ key , value } -> value
@@ -162,13 +179,15 @@ defmodule HashDict do
162
179
@ doc """
163
180
Checks if the dict has the given key.
164
181
"""
182
+ @ spec has_key? ( t , key :: term ) :: boolean
165
183
def has_key? ( dict , key ) do
166
184
match? { ^ key , _ } , dict_get ( dict , key )
167
185
end
168
186
169
187
@ doc """
170
188
Deletes a value from the dict.
171
189
"""
190
+ @ spec delete ( t , key :: term ) :: t
172
191
def delete ( ordered ( bucket: bucket , size: size ) = dict , key ) do
173
192
case bucket_delete ( bucket , key ) do
174
193
{ _ , 0 } ->
@@ -201,20 +220,23 @@ defmodule HashDict do
201
220
@ doc """
202
221
Returns the dict size.
203
222
"""
223
+ @ spec size ( t ) :: non_neg_integer
204
224
def size ( dict ) do
205
225
elem ( dict , 1 )
206
226
end
207
227
208
228
@ doc """
209
229
Returns an empty dict.
210
230
"""
231
+ @ spec empty ( t ) :: t
211
232
def empty ( _ ) do
212
233
ordered ( )
213
234
end
214
235
215
236
@ doc """
216
237
Converts the dict to a list.
217
238
"""
239
+ @ spec to_list ( t ) :: list ( { key :: term , value :: term } )
218
240
def to_list ( ordered ( bucket: bucket ) ) do
219
241
bucket
220
242
end
@@ -226,20 +248,24 @@ defmodule HashDict do
226
248
@ doc """
227
249
Get all keys in the dict.
228
250
"""
251
+ @ spec keys ( t ) :: list ( key :: term )
229
252
def keys ( dict ) do
230
253
dict_fold ( dict , [ ] , fn { k , _ } , acc -> [ k | acc ] end )
231
254
end
232
255
233
256
@ doc """
234
257
Get all values in the dict.
235
258
"""
259
+ @ spec values ( t ) :: list ( values :: term )
236
260
def values ( dict ) do
237
261
dict_fold ( dict , [ ] , fn { _ , v } , acc -> [ v | acc ] end )
238
262
end
239
263
240
264
@ doc """
241
265
Merges two dictionaries.
242
266
"""
267
+ @ spec merge ( t , t | Dict . t ) :: t
268
+ @ spec merge ( t , t | Dict . t , ( ( key :: term , value1 :: term , value2 :: term ) -> value :: term ) ) :: t
243
269
def merge ( dict , enum , callback // fn ( _k , _v1 , v2 ) -> v2 end )
244
270
245
271
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