Skip to content

Commit ded6077

Browse files
committed
Add some convenience macros to persistent_list_map!, and contains_key
function to IPersistentMap (which for now is still a part of persistent list map)
1 parent 21cddf5 commit ded6077

File tree

1 file changed

+110
-4
lines changed

1 file changed

+110
-4
lines changed

src/persistent_list_map.rs

Lines changed: 110 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
1616
use crate::maps::MapEntry;
1717
use crate::value::Value;
18+
use crate::traits;
1819

1920
use std::collections::HashMap;
2021
use 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.
3397
pub 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
}
37102
impl 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

55131
impl 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+
}
150248
impl 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 {
172270
mod 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

Comments
 (0)