generics: what can we do with an any type?

240 views
Skip to first unread message

Johannes Kohnen

unread,
Dec 15, 2021, 11:39:39 AM12/15/21
to golan...@googlegroups.com
Hello folks, 

I've stumbled over a thing and I don't understand if what I've found is intentionally possible by design...


Why can I compare int with == when it was instantiated from the "any" type parameter? 

The origin of my question is my implementation of a left right map which I've ported to generics.  While doing so I've uncovered a couple bugs in Jetbrains GoLand and reported them.  Except this one, because I've overlooked it and I now am confused:


In this line I compare two int values with !=, and this code compiles. Though, those value types were instantiated from the "any" type constraint.  GoLand reports an error in that line "Invalid operation: _v != v (the operator != is not defined on V)".

From my reading of the generics proposal GoLand is right, but the compiler says otherwise.  How exactly are the operations that are defined on an "any" type inferred?

Sorry if the answer is right there in the proposal; my reading comprehension fluctuates wildly these days. 

Cheers,
Johannes

Sean Liao

unread,
Dec 15, 2021, 12:01:41 PM12/15/21
to golang-nuts
when writing type parameterized code, it has to work with anything that could be passed to it.
but once instantiated, the type is known and it can be used with its concrete type

like `map` can be thought of as  declared to be `map[comparable]any`
but when you use it, the type is always known, eg. `map[string]int`

Brian Candler

unread,
Dec 15, 2021, 4:53:21 PM12/15/21
to golang-nuts
NewThing[int, int]()  returns  a map[int]int, and therefore that's the type of MySet in func runInt.

You can think of NewThing[T1, T2] as a family of functions, like

func NewThing_int_int() map[int]int { ... }
func NewThing_int_byteslice() map[int][]byte { ... }
... etc

w54n

unread,
Dec 16, 2021, 3:22:25 PM12/16/21
to golang-nuts
[]byte is a no comparable type.

quoting the docs:
comparable is an interface that is implemented by all comparable types
(booleans, numbers, strings, pointers, channels, interfaces,
arrays of comparable types, structs whose fields are all comparable types).
The comparable interface may only be used as a type parameter constraint,
not as the type of a variable.


for comparing bytes, use the "bytes" package.

here is an example from yours
On Wednesday, December 15, 2021 at 5:39:39 PM UTC+1 Johannes Kohnen wrote:

Howard C. Shaw III

unread,
Dec 16, 2021, 3:38:44 PM12/16/21
to golang-nuts
The code you wrote is using a generic value, but it is not itself generic. There is only one instantiated version of the runInt() function, and it knows (at compile-time!) that mySet is an map[int]int.

Make that function actually generic - something like:
func testThing[K comparable, V any](m map[K]V) {
        if m[1337] == 1337 {
                print("OK")
        } else {
                print("nope")
        }
}
and you get
./prog.go:xx:yy: cannot use 1337 (untyped int constant) as K value in map index 
./prog.go:xx:yy: cannot convert 1337 (untyped int constant) to V

Reply all
Reply to author
Forward
0 new messages