All types should have unrestricted comparisons (`==`, `!=`), but a few pre-declared types don't. Adding them would bridge a semantic gap between pre-declared and user-declared types, enabling all types to be used as map keys, and otherwise make reasoning about them more consistent and intuitive.
For the types that don't yet have unrestricted comparisons: - Functions: Compare the corresponding memory addresses. The time complexity is constant. - Maps: Compare the corresponding `*runtime.hmap` (pointer) values. The time complexity is constant. - Slices: Compare the corresponding `runtime.slice` (non-pointer struct) values. The time complexity is constant. Examples: ``` // Functions func F1() {} func F2() {} var _ = F1 == F1 // True var _ = F1 != F2 // True // Maps var M1 = map[int]int{} var M2 = map[int]int{} var _ = M1 == M1 // True var _ = M1 != M2 // True // Slices var S1 = make([]int, 2) var S2 = make([]int, 2) var _ = S1 == S1 // True var _ = S1 != S2 // True var _ = S1 == S1[:] // True because the lengths, capacities, and pointers are equal var _ = S1 != S1[:1] // True because the lengths aren't equal var _ = S1[:1] != S1[:1:1] // True because the capacities aren't equal var _ = S1 != append(S1, 0)[:2:2] // True because the pointers aren't equal ``` Function and map equality are consistent with channel equality, where non-nil channels are equal if they were created by the same call to `make`. Function values are equal if they were created by the same function literal or declaration. Map values are equal if they were created by the same map literal or the same call to `make`. Functions that are equal will always produce the same outputs and side effects given the same inputs and conditions; however, the reverse is not necessarily true. Maps that are equal will always contain the same keys and values; however, the reverse is not necessarily true. Slice equality is consistent with map equality. Slice values are equal if they have the same array pointer, length, and capacity. Slices that are equal will always have equal corresponding elements. However, like maps, slices that have equal corresponding elements are not necessarily equal. This approach to comparisons for functions, maps, and slices makes all values of those types immutable, and therefore usable as map keys. This would obviate the `comparable` constraint, since all type arguments would now satisfy it. In my opinion, this would make the language simpler and more consistent. Type variables could be used with comparison operations without needing to be constrained by `comparable`. If you think slice equality should incorporate element equality, here's an example for you: ``` type Slice1000[T any] struct { xs *[1000]T len, cap int } func (s Slice1000[T]) Get(i int) T { // ... return s.xs[i] } func (s Slice1000[T]) Set(i int, x T) { // ... s.xs[i] = x } var xs1, xs2 [1000]int var a = Slice1000[int]{&xs1, 1000, 1000} var b = Slice1000[int]{&xs2, 1000, 1000} var c = a == b ``` Do you expect `c` to be true? If not (it's false, by the way), then why would you expect `make([]int, 2) == make([]int, 2)` to be true? Any thoughts? -- 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. To view this discussion on the web visit https://groups.google.com/d/msgid/golang-nuts/8cdc4dae-95f8-4a38-b977-b5b228867c6fn%40googlegroups.com.