mirror of
https://github.com/kanaka/mal.git
synced 2024-11-13 01:43:50 +03:00
rust: core hash-map functions.
This commit is contained in:
parent
3744d56621
commit
b12d98e4e3
@ -5,7 +5,7 @@ use std::collections::HashMap;
|
||||
use std::io::File;
|
||||
|
||||
use types::{MalVal,MalRet,err_val,err_str,err_string,
|
||||
Int,Strn,List,Vector,Hash_Map,
|
||||
Nil,Int,Strn,List,Vector,Hash_Map,
|
||||
_nil,_true,_false,_int,string,list,func};
|
||||
use types;
|
||||
use readline;
|
||||
@ -126,6 +126,36 @@ pub fn time_ms(a:Vec<MalVal>) -> MalRet {
|
||||
|
||||
|
||||
// Hash Map functions
|
||||
pub fn assoc(a:Vec<MalVal>) -> MalRet {
|
||||
if a.len() < 3 {
|
||||
return err_str("Wrong arity to assoc call");
|
||||
}
|
||||
match *a[0] {
|
||||
Hash_Map(ref hm) => {
|
||||
types::_assoc(hm, a.slice(1,a.len()).to_vec())
|
||||
},
|
||||
Nil => {
|
||||
types::hash_mapv(a.slice(1,a.len()).to_vec())
|
||||
}
|
||||
_ => return err_str("assoc onto non-hash map"),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn dissoc(a:Vec<MalVal>) -> MalRet {
|
||||
if a.len() < 2 {
|
||||
return err_str("Wrong arity to dissoc call");
|
||||
}
|
||||
match *a[0] {
|
||||
Hash_Map(ref hm) => {
|
||||
types::_dissoc(hm, a.slice(1,a.len()).to_vec())
|
||||
},
|
||||
Nil => {
|
||||
Ok(_nil())
|
||||
}
|
||||
_ => return err_str("dissoc onto non-hash map"),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get(a:Vec<MalVal>) -> MalRet {
|
||||
if a.len() != 2 {
|
||||
return err_str("Wrong arity to get call");
|
||||
@ -133,7 +163,8 @@ pub fn get(a:Vec<MalVal>) -> MalRet {
|
||||
let a0 = a[0].clone();
|
||||
let hm: &HashMap<String,MalVal> = match *a0 {
|
||||
Hash_Map(ref hm) => hm,
|
||||
_ => return err_str("get of non-hash map"),
|
||||
Nil => return Ok(_nil()),
|
||||
_ => return err_str("get on non-hash map"),
|
||||
};
|
||||
match *a[1] {
|
||||
Strn(ref key) => {
|
||||
@ -146,6 +177,63 @@ pub fn get(a:Vec<MalVal>) -> MalRet {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn contains_q(a:Vec<MalVal>) -> MalRet {
|
||||
if a.len() != 2 {
|
||||
return err_str("Wrong arity to contains? call");
|
||||
}
|
||||
let a0 = a[0].clone();
|
||||
let hm: &HashMap<String,MalVal> = match *a0 {
|
||||
Hash_Map(ref hm) => hm,
|
||||
Nil => return Ok(_false()),
|
||||
_ => return err_str("contains? on non-hash map"),
|
||||
};
|
||||
match *a[1] {
|
||||
Strn(ref key) => {
|
||||
match hm.contains_key(key) {
|
||||
true => Ok(_true()),
|
||||
false => Ok(_false()),
|
||||
}
|
||||
},
|
||||
_ => return err_str("contains? with non-string key"),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn keys(a:Vec<MalVal>) -> MalRet {
|
||||
if a.len() != 1 {
|
||||
return err_str("Wrong arity to keys call");
|
||||
}
|
||||
let a0 = a[0].clone();
|
||||
let hm: &HashMap<String,MalVal> = match *a0 {
|
||||
Hash_Map(ref hm) => hm,
|
||||
Nil => return Ok(_nil()),
|
||||
_ => return err_str("contains? on non-hash map"),
|
||||
};
|
||||
if hm.len() == 0 { return Ok(_nil()); }
|
||||
let mut keys = vec![];
|
||||
for k in hm.keys() {
|
||||
keys.push(string(k.to_string()));
|
||||
}
|
||||
Ok(list(keys))
|
||||
}
|
||||
|
||||
pub fn vals(a:Vec<MalVal>) -> MalRet {
|
||||
if a.len() != 1 {
|
||||
return err_str("Wrong arity to values call");
|
||||
}
|
||||
let a0 = a[0].clone();
|
||||
let hm: &HashMap<String,MalVal> = match *a0 {
|
||||
Hash_Map(ref hm) => hm,
|
||||
Nil => return Ok(_nil()),
|
||||
_ => return err_str("contains? on non-hash map"),
|
||||
};
|
||||
if hm.len() == 0 { return Ok(_nil()); }
|
||||
let mut vals = vec![];
|
||||
for k in hm.values() {
|
||||
vals.push(k.clone());
|
||||
}
|
||||
Ok(list(vals))
|
||||
}
|
||||
|
||||
|
||||
// Sequence functions
|
||||
pub fn cons(a:Vec<MalVal>) -> MalRet {
|
||||
@ -329,7 +417,12 @@ pub fn ns() -> HashMap<String,MalVal> {
|
||||
ns.insert("vector?".to_string(), func(types::vector_q));
|
||||
ns.insert("hash-map".to_string(), func(types::hash_mapv));
|
||||
ns.insert("map?".to_string(), func(types::hash_map_q));
|
||||
ns.insert("assoc".to_string(), func(assoc));
|
||||
ns.insert("dissoc".to_string(), func(dissoc));
|
||||
ns.insert("get".to_string(), func(get));
|
||||
ns.insert("contains?".to_string(), func(contains_q));
|
||||
ns.insert("keys".to_string(), func(keys));
|
||||
ns.insert("vals".to_string(), func(vals));
|
||||
|
||||
ns.insert("sequential?".to_string(), func(types::sequential_q));
|
||||
ns.insert("cons".to_string(), func(cons));
|
||||
|
@ -245,12 +245,12 @@ pub fn vector_q(a:Vec<MalVal>) -> MalRet {
|
||||
|
||||
// Hash Maps
|
||||
pub fn hash_map(hm: HashMap<String,MalVal>) -> MalVal { Rc::new(Hash_Map(hm)) }
|
||||
pub fn hash_mapv(seq: Vec<MalVal>) -> MalRet {
|
||||
if seq.len() % 2 == 1 {
|
||||
return err_str("odd number of elements to hash-map");
|
||||
pub fn _assoc(hm: &HashMap<String,MalVal>, a:Vec<MalVal>) -> MalRet {
|
||||
if a.len() % 2 == 1 {
|
||||
return err_str("odd number of hash-map keys/values");
|
||||
}
|
||||
let mut new_hm: HashMap<String,MalVal> = HashMap::new();
|
||||
let mut it = seq.iter();
|
||||
let mut new_hm = hm.clone();
|
||||
let mut it = a.iter();
|
||||
loop {
|
||||
let k = match it.next() {
|
||||
Some(mv) => match *mv.clone() {
|
||||
@ -264,6 +264,25 @@ pub fn hash_mapv(seq: Vec<MalVal>) -> MalRet {
|
||||
}
|
||||
Ok(Rc::new(Hash_Map(new_hm)))
|
||||
}
|
||||
pub fn _dissoc(hm: &HashMap<String,MalVal>, a:Vec<MalVal>) -> MalRet {
|
||||
let mut new_hm = hm.clone();
|
||||
let mut it = a.iter();
|
||||
loop {
|
||||
let k = match it.next() {
|
||||
Some(mv) => match *mv.clone() {
|
||||
Strn(ref s) => s.to_string(),
|
||||
_ => return err_str("key is not a string in hash-map call"),
|
||||
},
|
||||
None => break,
|
||||
};
|
||||
new_hm.remove(&k);
|
||||
}
|
||||
Ok(Rc::new(Hash_Map(new_hm)))
|
||||
}
|
||||
pub fn hash_mapv(seq: Vec<MalVal>) -> MalRet {
|
||||
let new_hm: HashMap<String,MalVal> = HashMap::new();
|
||||
_assoc(&new_hm, seq)
|
||||
}
|
||||
pub fn hash_map_q(a:Vec<MalVal>) -> MalRet {
|
||||
if a.len() != 1 {
|
||||
return err_str("Wrong arity to map? call");
|
||||
@ -274,6 +293,7 @@ pub fn hash_map_q(a:Vec<MalVal>) -> MalRet {
|
||||
}
|
||||
}
|
||||
|
||||
// Functions
|
||||
pub fn func(f: fn(Vec<MalVal>) -> MalRet ) -> MalVal {
|
||||
Rc::new(Func(f))
|
||||
}
|
||||
|
@ -108,29 +108,6 @@
|
||||
(vector 3 4 5)
|
||||
;=>[3 4 5]
|
||||
|
||||
;; Testing conj function
|
||||
(conj (list) 1)
|
||||
;=>(1)
|
||||
(conj (list 1) 2)
|
||||
;=>(2 1)
|
||||
(conj (list 2 3) 4)
|
||||
;=>(4 2 3)
|
||||
(conj (list 2 3) 4 5 6)
|
||||
;=>(6 5 4 2 3)
|
||||
(conj (list 1) (list 2 3))
|
||||
;=>((2 3) 1)
|
||||
|
||||
(conj [] 1)
|
||||
;=>[1]
|
||||
(conj [1] 2)
|
||||
;=>[1 2]
|
||||
(conj [2 3] 4)
|
||||
;=>[2 3 4]
|
||||
(conj [2 3] 4 5 6)
|
||||
;=>[2 3 4 5 6]
|
||||
(conj [1] [2 3])
|
||||
;=>[1 [2 3]]
|
||||
|
||||
(map? [])
|
||||
;=>false
|
||||
|
||||
@ -207,6 +184,30 @@
|
||||
;=>2
|
||||
|
||||
|
||||
;;
|
||||
;; Testing conj function
|
||||
(conj (list) 1)
|
||||
;=>(1)
|
||||
(conj (list 1) 2)
|
||||
;=>(2 1)
|
||||
(conj (list 2 3) 4)
|
||||
;=>(4 2 3)
|
||||
(conj (list 2 3) 4 5 6)
|
||||
;=>(6 5 4 2 3)
|
||||
(conj (list 1) (list 2 3))
|
||||
;=>((2 3) 1)
|
||||
|
||||
(conj [] 1)
|
||||
;=>[1]
|
||||
(conj [1] 2)
|
||||
;=>[1 2]
|
||||
(conj [2 3] 4)
|
||||
;=>[2 3 4]
|
||||
(conj [2 3] 4 5 6)
|
||||
;=>[2 3 4 5 6]
|
||||
(conj [1] [2 3])
|
||||
;=>[1 [2 3]]
|
||||
|
||||
;;
|
||||
;; Testing metadata
|
||||
(meta [1 2 3])
|
||||
|
Loading…
Reference in New Issue
Block a user