Correction on the self-reference example: a0 := A{} // equal a1 := A{a0, A{}} a1[0] = a1 a2 := A{a1, a1[1]} // not equal a3 := A{A{a1, a1[1]}, a1[1]}
Thanks, Matt On Tuesday, January 30, 2018 at 5:19:44 PM UTC-6, matthe...@gmail.com wrote: > > - When slices can be compared, they can be used as map keys. What happens >> if the contents of a slice are changed after it has been added to a map? > > > I’m not too familiar with Go map internals, but my thought is the key hash > would depend on the backing array values. Go maps also allow reading the > keys back using iteration so the slice backing array (up to length) would > have to be copied. If the slice contents are changed then that would be a > different key and the original key would be intact. > > - It is possible to have self-referential slices [1]. How would >> comparison work in such a case? > > > Perhaps a slice of slices would compare the contents, the slice headers, > to each other like structs. > > type A []A > > // not equal > a0 := A{A{}} > a1 := A{} > > // not equal > a2 := A{A{}, A{A{}}} > a3 := A{A{}, A{A{}}} > > // not equal > a4 := A{a0} > a5 := A{A{A{}}} > > // equal > a6 := A{a0} > a7 := A{a0} > > // equal > a8 := A{a0} > a8[0] = a1 > a9 := A{a1} > > The self-reference: > > a0 := A{} > // equal > a1 := A{a0, A{}} > a1[0] = a1 > a2 := A{a0, a1[1]} > // not equal > a3 := A{A{}, a1[1]} > > I'm not sure about this one since it seems to go against the idea of slice > comparison by values. > > Matt > > On Tuesday, January 30, 2018 at 2:33:38 PM UTC-6, rog wrote: >> >> Two significant issues that need to be thought about: >> >> - When slices can be compared, they can be used as map keys. What happens >> if the contents of a slice are changed after it has been added to a map? >> >> - It is possible to have self-referential slices [1]. How would >> comparison work in such a case? >> >> >> [1] https://play.golang.org/p/lTqhKjD842K >> >> On 30 Jan 2018 16:45, <matthe...@gmail.com> wrote: >> >>> Here’s a draft for a Go 2 proposal that I’d like to add to the issue >>> tracker since there’s no discussion there about this: >>> >>> Slices should have equality defined. >>> >>> https://golang.org/doc/faq#map_keys >>> >>> Map lookup requires an equality operator, which slices do not implement. >>>> They don't implement equality because equality is not well defined on such >>>> types; there are multiple considerations involving shallow vs. deep >>>> comparison, pointer vs. value comparison, how to deal with recursive >>>> types, >>>> and so on. >>> >>> >>> This proposal allows slices to be used as map keys and for comparison >>> with == and !=. >>> >>> https://golang.org/ref/spec#Comparison_operators >>> >>> Slice, map, and function values are not comparable. >>> >>> >>> An initial proposal is that slices are compared by nil versus non-nil, >>> length and backing array pointer, and then by the rules for array if length >>> is equal but different arrays are pointed: >>> >>> Array values are comparable if values of the array element type are >>>> comparable. Two array values are equal if their corresponding elements are >>>> equal. >>> >>> >>> reflect.DeepEqual defines a similar slice equality except “deeply equal” >>> defines additional criteria: https://golang.org/pkg/reflect/#DeepEqual >>> >>> Slice values are deeply equal when all of the following are true: they >>>> are both nil or both non-nil, they have the same length, and either they >>>> point to the same initial entry of the same underlying array (that is, >>>> &x[0] == &y[0]) or their corresponding elements (up to length) are deeply >>>> equal. Note that a non-nil empty slice and a nil slice (for example, >>>> []byte{} and []byte(nil)) are not deeply equal. >>> >>> >>> A use case for me was a map keyed by varying length paths where the map >>> was not shared between different path generating computations. With this >>> proposal such a type could have shared generated paths as keys. >>> >>> Ian suggests in a [this] golang-nuts thread that there are varying use >>> cases: >>> >>> The problem is that different programs need different things for slice >>>> equality. Some want pointer equality as you suggest. Some want element >>>> comparisons, as is done for array equality. Without an obvious semantics >>>> for the operation, the language omits it entirely. >>>> >>> >>> But I don’t know where slice pointer equality would be useful. I'm also >>> not clear on the recursive type problem. >>> >>> Matt >>> >>> On Monday, July 4, 2016 at 2:29:18 AM UTC-5, Chad wrote: >>>> >>>> I realize that the issue might be about changing/ adding a builtin: >>>> >>>> - either add a builtin deep value Comparison function (via >>>> reflection) >>>> - or add a snapshot type refinement which triggers the allocation >>>> of an immutable copy of a reference type >>>> (and we would recover the behaviour of the string implementation >>>> which is a special case of []byte snapshot, i.e. a value type*) >>>> >>>> I would still expect the behaviour previously mentioned for the "==" >>>> operator. >>>> >>>> (*) I keep using reference/value type terminology but it is indeed >>>> slightly tricky. But for lack of a better one... >>>> >>> -- >>> You received this message because you are subscribed to the Google >>> Groups "golang-nuts" group. >>> To unsubscribe from this group and stop receiving emails from it, send >>> an email to golang-nuts...@googlegroups.com. >>> For more options, visit https://groups.google.com/d/optout. >>> >> -- You received this message because you are subscribed to the Google Groups "golang-nuts" group. To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.