1515
1616use crate :: maps:: MapEntry ;
1717use crate :: value:: Value ;
18+ use crate :: traits;
1819
1920use std:: collections:: HashMap ;
2021use std:: convert:: From ;
@@ -27,12 +28,76 @@ pub enum PersistentListMap {
2728 Map ( Rc < PersistentListMap > , MapEntry ) ,
2829 Empty ,
2930}
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
3296/// A PersistentListMap.
3397pub trait IPersistentMap {
3498 fn get ( & self , key : & Rc < Value > ) -> Rc < Value > ;
3599 fn assoc ( & self , key : Rc < Value > , value : Rc < Value > ) -> Self ;
100+ fn contains_key ( & self , key : & Rc < Value > ) -> bool ;
36101}
37102impl IPersistentMap for PersistentListMap {
38103 // @TODO make fn of ILookup
@@ -50,6 +115,17 @@ impl IPersistentMap for PersistentListMap {
50115 fn assoc ( & self , key : Rc < Value > , val : Rc < Value > ) -> PersistentListMap {
51116 PersistentListMap :: Map ( Rc :: new ( self . clone ( ) ) , MapEntry { key, val } )
52117 }
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+ }
53129}
54130
55131impl IPersistentMap for Rc < PersistentListMap > {
@@ -71,6 +147,17 @@ impl IPersistentMap for Rc<PersistentListMap> {
71147 MapEntry { key, val } ,
72148 ) )
73149 }
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+ }
74161}
75162
76163// The purpose of these functions are no longer to implement conversion,
@@ -146,7 +233,18 @@ impl FromIterator<MapEntry> for PersistentListMap {
146233////////////////////////////////////////////////////////////////////////////////////////////////////
147234// End Iteration
148235////////////////////////////////////////////////////////////////////////////////////////////////////
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+ }
150248impl fmt:: Display for PersistentListMap {
151249 fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
152250 let mut as_str = String :: from ( "{" ) ;
@@ -172,10 +270,11 @@ impl fmt::Display for PersistentListMap {
172270mod tests {
173271 use crate :: persistent_list_map:: * ;
174272 use crate :: symbol:: Symbol ;
273+ use crate :: keyword:: Keyword ;
175274 use crate :: value:: ToValue ;
176275
177276 #[ test]
178- fn test_persistent_list_map ( ) {
277+ fn persistent_list_map ( ) {
179278 let map1 = vec ! [
180279 MapEntry {
181280 key: Symbol :: intern( "a" ) . to_rc_value( ) ,
@@ -202,4 +301,11 @@ mod tests {
202301 println ! ( "{}" , map3) ;
203302 println ! ( "{}" , map4) ;
204303 }
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+ }
205311}
0 commit comments