15
15
16
16
use crate :: maps:: MapEntry ;
17
17
use crate :: value:: Value ;
18
+ use crate :: traits;
18
19
19
20
use std:: collections:: HashMap ;
20
21
use std:: convert:: From ;
@@ -27,12 +28,76 @@ pub enum PersistentListMap {
27
28
Map ( Rc < PersistentListMap > , MapEntry ) ,
28
29
Empty ,
29
30
}
30
- // Again, only using strange IBlah convention to reflect the Clojure base
31
- // @TODO really though .. just rethink this
31
+ impl Eq for PersistentListMap { }
32
+
33
+ /// map_entry!("doc", "this is a docstring");
34
+ #[ macro_export]
35
+ macro_rules! map_entry {
36
+ ( $key: expr, $value: expr) => { {
37
+ MapEntry {
38
+ key: Keyword :: intern( $key) . to_rc_value( ) ,
39
+ val: $value. to_rc_value( ) ,
40
+ }
41
+ } } ;
42
+ }
43
+
44
+ /// persistent_list_map!(map_entry!("key1", "value1"), map_entry!("key2", "value2"));
45
+ #[ macro_export]
46
+ macro_rules! persistent_list_map {
47
+ ( $( $kv: expr) ,* ) => {
48
+ {
49
+ let mut temp_vec = Vec :: new( ) ;
50
+ $(
51
+ temp_vec. push( $kv) ;
52
+ ) *
53
+ temp_vec. into_iter( ) . collect:: <PersistentListMap >( )
54
+ }
55
+ } ;
56
+ { $( $key: expr => $val: expr) ,* } => {
57
+ {
58
+ let mut temp_vec = Vec :: new( ) ;
59
+ $(
60
+ temp_vec. push( map_entry!( $key, $val) ) ;
61
+ ) *
62
+ temp_vec. into_iter( ) . collect:: <PersistentListMap >( )
63
+ }
64
+ } ;
65
+ }
66
+
67
+ /// merge!(base_meta(name, ns), map_entry!("key1", "value1"), map_entry!("key2", "value2"));
68
+ #[ macro_export]
69
+ macro_rules! merge {
70
+ ( $plistmap: expr, $( $kv: expr) , * ) => {
71
+ {
72
+ let mut temp_plistmap_as_vec = $plistmap. clone( ) . iter( ) . collect:: <Vec <MapEntry >>( ) ;
73
+ $(
74
+ temp_plistmap_as_vec. push( $kv) ;
75
+ ) *
76
+ temp_plistmap_as_vec. into_iter( ) . collect:: <PersistentListMap >( )
77
+ }
78
+ } ;
79
+ }
80
+
81
+ /// merge!(base_meta(name, ns), map_entry!("key1", "value1"), map_entry!("key2", "value2"));
82
+ #[ macro_export]
83
+ macro_rules! merge_maps {
84
+ ( $plistmap: expr, $( $kv: expr) , * ) => {
85
+ {
86
+ let mut temp_plistmap_as_vec = $plistmap. clone( ) . iter( ) . collect:: <Vec <MapEntry >>( ) ;
87
+ $(
88
+ temp_plistmap_as_vec. push( $kv) ;
89
+ ) *
90
+ temp_plistmap_as_vec. into_iter( ) . collect:: <PersistentListMap >( )
91
+ }
92
+ } ;
93
+ }
94
+
95
+ // @TODO put note on IBlah traits in doc
32
96
/// A PersistentListMap.
33
97
pub trait IPersistentMap {
34
98
fn get ( & self , key : & Rc < Value > ) -> Rc < Value > ;
35
99
fn assoc ( & self , key : Rc < Value > , value : Rc < Value > ) -> Self ;
100
+ fn contains_key ( & self , key : & Rc < Value > ) -> bool ;
36
101
}
37
102
impl IPersistentMap for PersistentListMap {
38
103
// @TODO make fn of ILookup
@@ -50,6 +115,17 @@ impl IPersistentMap for PersistentListMap {
50
115
fn assoc ( & self , key : Rc < Value > , val : Rc < Value > ) -> PersistentListMap {
51
116
PersistentListMap :: Map ( Rc :: new ( self . clone ( ) ) , MapEntry { key, val } )
52
117
}
118
+ fn contains_key ( & self , key : & Rc < Value > ) -> bool {
119
+ match self {
120
+ PersistentListMap :: Map ( parent, entry) => {
121
+ if entry. key == * key {
122
+ return true ;
123
+ }
124
+ parent. contains_key ( key)
125
+ } ,
126
+ PersistentListMap :: Empty => false
127
+ }
128
+ }
53
129
}
54
130
55
131
impl IPersistentMap for Rc < PersistentListMap > {
@@ -71,6 +147,17 @@ impl IPersistentMap for Rc<PersistentListMap> {
71
147
MapEntry { key, val } ,
72
148
) )
73
149
}
150
+ fn contains_key ( & self , key : & Rc < Value > ) -> bool {
151
+ match & * * self {
152
+ PersistentListMap :: Map ( parent, entry) => {
153
+ if entry. key == * key {
154
+ return true ;
155
+ }
156
+ parent. contains_key ( key)
157
+ } ,
158
+ PersistentListMap :: Empty => false
159
+ }
160
+ }
74
161
}
75
162
76
163
// The purpose of these functions are no longer to implement conversion,
@@ -146,7 +233,18 @@ impl FromIterator<MapEntry> for PersistentListMap {
146
233
////////////////////////////////////////////////////////////////////////////////////////////////////
147
234
// End Iteration
148
235
////////////////////////////////////////////////////////////////////////////////////////////////////
149
-
236
+ impl traits:: IMeta for PersistentListMap {
237
+ fn meta ( & self ) -> PersistentListMap {
238
+ // @TODO implement
239
+ PersistentListMap :: Empty
240
+ }
241
+ }
242
+ impl traits:: IObj for PersistentListMap {
243
+ fn with_meta ( & self , meta : PersistentListMap ) -> PersistentListMap {
244
+ // @TODO implement
245
+ self . clone ( )
246
+ }
247
+ }
150
248
impl fmt:: Display for PersistentListMap {
151
249
fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
152
250
let mut as_str = String :: from ( "{" ) ;
@@ -172,10 +270,11 @@ impl fmt::Display for PersistentListMap {
172
270
mod tests {
173
271
use crate :: persistent_list_map:: * ;
174
272
use crate :: symbol:: Symbol ;
273
+ use crate :: keyword:: Keyword ;
175
274
use crate :: value:: ToValue ;
176
275
177
276
#[ test]
178
- fn test_persistent_list_map ( ) {
277
+ fn persistent_list_map ( ) {
179
278
let map1 = vec ! [
180
279
MapEntry {
181
280
key: Symbol :: intern( "a" ) . to_rc_value( ) ,
@@ -202,4 +301,11 @@ mod tests {
202
301
println ! ( "{}" , map3) ;
203
302
println ! ( "{}" , map4) ;
204
303
}
304
+ #[ test]
305
+ fn contains_key ( ) {
306
+ let map1 = persistent_list_map ! { "a" => 12 , "b" => 13 } ;
307
+ assert ! ( map1. contains_key( & Keyword :: intern( "a" ) . to_rc_value( ) ) ) ;
308
+ assert ! ( map1. contains_key( & Keyword :: intern( "b" ) . to_rc_value( ) ) ) ;
309
+ assert ! ( !map1. contains_key( & Keyword :: intern( "c" ) . to_rc_value( ) ) ) ;
310
+ }
205
311
}
0 commit comments