I am building a heterogeneous map for an interpreted programming language in Go. As part of the language, I want to be able to stringify any value for printing.
I have the following code:
// ObjKind helps determine what kind of object it is
type ObjKind uint
// Obj is an interface for all values in golflang.
// Any values must implement this interface.
type Obj interface {
Bool() bool
Equal(o Obj) bool
Kind() ObjKind // the kind of this object
Repr() string // debug representation of this object
String() string // stringified representation of this object, for printing
}
type Map map[Obj]Obj
func (m Map) String() string {
vs := []string{}
for k, v := range m {
vs = append(vs, fmt.Sprintf("%s:%s", k.String(), v.String()))
}
return fmt.Sprintf("{%s}", strings.Join(vs, ","))
}
However, this implementation has the flaw that iterating over keys in a map do not have consistent order, leading to my unit tests failing by having the elements in different orders each run. I cannot take the maps.Keys() and sort it, because this is a heterogenous map and the elements aren't necessarily the same type nor comparable (in the language's semantics).
Is there a way to guarantee an ordered iteration through such a map's keys, so that String() here consistently outputs the same string?
assert.Equals(obj.String(), "{a:A,b:B}")you could instead assertassert.Equal(2, strings.Count(obj.String(), ":"))(assert that there are 2 pairs) &&assert.Contains(obj.String(), "a:A")&&assert.Contains(obj.String(), "b:B").