Are there any real packages out there using these techniques?
Are there any real packages out there using these techniques?
I was unclear, I'm afraid. You can reorder the type parameters, it just changes which of them you need to specify: https://go.dev/play/p/oDIFl3fZiPl
The point is that you can only leave off elements from the end of the list, to have them automatically inferred.
> Are there any real packages out there using these techniques?
I think so far, the usage of generics for containers in Go is still relatively sparse, in public code. I think in part that is because the documentation of how to do that is relatively sparse. That is part of the motivation for the post, to have a bit of somewhat official documentation for these things, so they become more widely known.
The standard library is just starting to add generic containers: https://github.com/golang/go/issues/69559 And part of that is discussing how we want to do things like this: https://github.com/golang/go/issues/70471
That being said, I have used the pointer receiver thing in my dayjob. One example is protobuf. We have a generic helper to set a protobuf enum from the environment. Because of how the API was designed, that required a pointer receiver constraint.
The article mentions using the function version to implement all others, but also that the method version would be optimized better.
Would the compiler be able to inline MethodTree's compare even though it's passed in as a function variable to node.insert?
My larger point though, is that with the `func` field the compiler can't optimize things even in principle. A user could always reassign this field (if nothing else using `*t = *new(FuncTree)`). So the compiler has to treat it as a dynamic call categorically. If the `func` is passed as a function, then at least in principle, it can prove that this function can't get modified during the call so can make optimization decisions based on what is being passed to it. For example, even without inlining, a future compiler might decide to compile two versions of `node.insert`, one with general dynamic calls and one specific one for a specific static function.
My philosophy when it comes to API decisions that impact performance is, not to make them too dependent on what the compiler is doing today, but just to take care there is enough information there, that the compiler can do an optimization in principle - which means it either will do it today, or we can make it smarter in the future, if it becomes a problem.