Closed
Description
Author background
- Would you consider yourself a novice, intermediate, or experienced Go programmer? experienced
- What other languages do you have experience with? python, lua, assembly, ...
Related proposals
- Has this idea, or one like it, been proposed before? a quick
is:issue label:proposal maps in:title
search suggest to me noIf so, how does this proposal differ?
- Does this affect error handling? No
If so, how does this differ from previous error handling proposals?
- Is this about generics? No
If so, how does this relate to the accepted design and other generics proposals?
This is based with concepts of #63221 (but could be refactored to not be).
In case #63221 is refused then I think this is especially valuable.
Proposal
- What is the proposed change?
Allow to define multiple types in the keys of maps:
type edges map[string, string]struct{}
And have it be equivalent to creating a tuple of the same types:
type edges map[struct(string, string)]struct{}
Indexing into the map would be sugar for pack
:
func (m edges) Link(a, b) {
m[a, b] = pack()
}
func (m edges) IsValidPath(path ...string) bool {
a := path[0]
for _, b := range path {
if _, ok := m[a, b]; !ok {
return false
}
a = b
}
return bool
}
Would be:
func (m edges) Link(a, b string) {
m[pack(a, b)] = pack()
}
func (m edges) IsValidPath(path ...string) bool {
a := path[0]
for _, b := range path {
if _, ok := m[pack(a, b)]; !ok {
return false
}
a = b
}
return bool
}
Lastly maps literals would get the same treatment:
m := edges{"Nantes", "Paris": pack()}
Into:
m := edges{pack("Nantes", "Paris"): pack()}
- Who does this proposal help, and why?
Current alternatives are:- Create an anonymous struct for the key (or use an array if the usecase fits for it).
Which works but is verbose. - Use proposal: spec: tuples as sugar for structs #63221, this is not yet accepted and is still a more verbose.
- Use nested maps, this gives a good enough syntax
m[a][b]
but is very awkward to deal with when considering keys that can be missing, awkward collection when deleting elements and adding elements which need to check if the inner map exists. This gets very bad to use fast when using lots of elements in the key. And performance is in almost all cases worst. *This fits unique edge cases you need to iterate over an inner map, or pass the inner map around.
- Create an anonymous struct for the key (or use an array if the usecase fits for it).
- Please describe as precisely as possible the change to the language.
KeyType = Type .
→KeyType TypeList .
TypeList is turned into an anonymous struct using proposal: spec: tuples as sugar for structs #63221struct
tuple.KeyList = Key { "," Key } .
KeyedElement = [ Key ":" ] Element .
→KeyedElement = [ KeyList ":" ] Element .
, specifying more than one key is invalid except for map where it is then packed into one value using proposal: spec: tuples as sugar for structs #63221pack
rules.Index = "[" Expression [ "," ] "]" .
→Index = "[" ExpressionList [ "," ] "]" .
, specifying more than one key is invalid except for map where it is then packed into one value using proposal: spec: tuples as sugar for structs #63221pack
rules.
- What would change in the language spec?
- see above
- Please also describe the change informally, as in a class teaching Go.
Ok so imagine you just explained and demonstrated how maps exists.
Well you can have multiple keys:
m := map[int, int, int]block{ 0, 0, 0: stone, 0, 1, 0: dirt, } m[0, 2, 0] = water fmt.Println(m[0, 1, 0])
- Is this change backward compatible? Yes
Breaking the Go 1 compatibility guarantee is a large cost and requires a large benefit.
Show example code before and after the change.BeforeAfter
- Orthogonality: how does this change interact or overlap with existing features? It makes maps with multi-factorial keys more readable and easier to use.
- Is the goal of this change a performance improvement? No
If so, what quantifiable improvement should we expect?How would we measure it?
Costs
- Would this change make Go easier or harder to learn, and why? I think this is very slightly harder, I belive
map[string, float64, int]complex128
andm["a", 42, 1337]
are self explanatory however in the rare cases someone would try to integrate this with iteration andencoding/json
(throughreflect
) this would yield surprising results, at least if theses aren't updated to have special behavior for tuples. - What is the cost of this proposal? (Every language change has a cost). More lines in the spec. Require the compiler to read and understand map keys and canonicalize them into single type forms.
- How many tools (such as vet, gopls, gofmt, goimports, etc.) would be affected? I don't know, this could range to all of them to few of them depending on whether or not updating
go/parser
would be enough. - What is the compile time cost? None
- What is the run time cost? None
- Can you describe a possible implementation? Update the parser following rules described above, when walking the AST right after binding types to names run proposal: spec: tuples as sugar for structs #63221 packing (create anonymous structs with
F0
,F1
, ...Fn
names) on map keys and map indexes with multiple entries. - Do you have a prototype? (This is not required.) No