// MapEquiv returns true if its arguments are equivalent as maps. // First argument is an iseq.PMap. // Second argument must be convertible to a map. (Someeday we may handle go maps.) // To be equivalent, must contain equivalent keys and values. func MapEquiv(m1 iseq.PMap, obj interface{}) bool { if m1 == obj { return true } if _, ok := obj.(map[interface{}]interface{}); ok { // TODO: figure out how to handle go maps return false } if m2, ok := obj.(iseq.PMap); ok { if m1.Count() != m2.Count() { return false } for s := m1.Seq(); s != nil; s = s.Next() { me := s.First().(iseq.MapEntry) found := m2.ContainsKey(me.Key()) if !found || !Equiv(me.Val(), m2.ValAt(me.Key())) { return false } } return true } return false }
// MapCons adds (conses) a new key/value pair onto an iseq.PMap // A MapEntry adds its key/value. // A PVector uses v[2*i] v[2*i+1] as key/value pairs // Otherwise, we need a sequence of iseq.MapEntry values // Assumes its argument is one of the above; else panics func MapCons(m iseq.PMap, o interface{}) iseq.PMap { if me, ok := o.(iseq.MapEntry); ok { return m.AssocM(me.Key(), me.Val()) } if v, ok := o.(iseq.PVector); ok { if v.Count() != 2 { panic("Vector arg to map cons must be a pair") } return m.AssocM(v.Nth(0), v.Nth(1)) } ret := m for s := ConvertToSeq(o); s != nil; s = s.Next() { me := s.First().(iseq.MapEntry) ret = ret.AssocM(me.Key(), me.Val()) } return ret }
// HashMap computes a hash for an iseq.PMap func HashMap(m iseq.PMap) uint32 { return HashUnordered(m.Seq()) }