-
Notifications
You must be signed in to change notification settings - Fork 17.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
proposal: spec: add comparable w/o interfaces #49587
Comments
Wouldn't this need to exclude any interface type, not just All interfaces are considered comparable:
|
I feel like there's some really useful headroom where preferring the proposed This approach doesn't require reflection and does set the compiler up to be useful. It doesn't prohibit accidents with |
I believe that writing a generic function that uses the |
comparable
type which is excluded interface{}
typecomparable
constraint that excludes interface types
comparable
constraint that excludes interface types
Thanks, everyone. If a provider of a third-party package does some kind of validation using I have noticed something while writing this proposal. I thought that the real problem was that Go not provide a type that could not be configured no matter how hard Go user tried. For example, a If this type is provided, users who have the same problem as I do will be able to write their own definitions. For example, let's call it type NonInterfaceComparable interface {
constraints.Integer | constraints.Float | constraints.Complex | ~string | comparablestruct
} What do you all think? |
I've considered type NonInterfaceComparable[T any] interface {
~bool |
constraints.Integer |
constraints.Float |
constraints.Complex |
~string | // String values
~*T | // Pointer values
~chan T | // Channel values
~<-chan T | // Receive only channel values
~chan<- T | // Send only channel values
comparablestruct |
comparablearray
} To represent pointers and channels, this interface requires a type argument. |
We should use the generics changes for a while before we decide we need two different kinds of comparable. I suggest we decline this and return in a few years if the need is still strongly felt. |
This proposal has been added to the active column of the proposals project |
To address your second point first: it's not quite as simple as that. The code there can still panic when one argument is nil. Getting it right is more awkward and has more runtime overhead: https://gotipplay.golang.org/p/hJQ1TzxVeLl; in fact it's still not right. With respect to your first point, I'm not so sure. One pattern that I've seen emerging multiple times so far in the generic Go code that I've written is that of hiding type parameters behind interfaces (sometimes known as "type erasure", I believe). This pattern makes it possible to take a value with type parameters and put it inside a heterogeneous collection such as a slice or map. Here's a simple example: https://gotipplay.golang.org/p/WgMcZIkVxPs . In general, given a type Unfortunately, when
and then we can write a transformation from My initial thought when I first came across this this was that we should just make Then I realised that perhaps there's a more interesting potential semantic here that could be introduced without loss of backward compatibility: we could make a There are various places in the standard library that would probably have used this constraint if they could (for example the key value provided to The only problem that I can see with allowing I propose that we leave the above possibility open without committing to it by tightening the current type parameter proposal so that it does not consider interface types to be comparable. For example, this code would not compile:
If at some future date we allow
With respect to this proposal, I'm suggesting that instead of adding a new kind of comparable type, we can change the existing |
@rogpeppe Thanks for the detailed explanation. My motivation for this proposal was to question the possibility of including This is an example of https://gotipplay.golang.org/p/ukN96RW8Pui I also often see code that returns an interface as a return value and does something with the result. In this example, we return https://gotipplay.golang.org/p/f3LMqLbIRcx I would be happy if
if we choose the third option, I think this should be in time for the release of Generics. Because it's related to maintaining backward compatibility. |
@Code-Hex Looking specifically at Changing So let's wait and see whether this is a real problem in practice before we introduce a new kind of |
@ianlancetaylor Thank you for your answer. And sorry about that. I was confused because
I agree with you on this point as well. I also think that adding a new
I agree with rsc's opinion. Because I can't think of anything that would really be a problem now.
However, it would obviously be helpful to have a I've been experimenting with generics in this repository. It is intended to be provided as a library. The |
Why? From what I can tell this is a generic caching library. It seems very useful to me, to instantiate a cache using interface-types. For example, I might have an encoding library, which caches encoders for IMO your specific use-case should just use Obviously it would be preferable (all things being equal) to be able to catch buggy usage of your library statically. But that's just not how the language at large works. The panic you generate is akin to the panic generated by using an incomparable value as a key in a |
@Merovius Thanks. This is because interfaces are not statically guaranteed to be comparable. I thought it would be best if the compiler could guarantee that only Unfortunately, it is not. (it's acceptable like
As I write this message, I am thinking that what I really wanted was what @rogpeppe said. I know this is a bit off-topic, but does the feasibility exist for this?
|
I'm not sold on the idea of
I'd guess we would end up with a lot of Then there's also the question Ian brings up here - what about composite types? Currently they are comparable and we can't break that. But for this idea to be effective, we definitely would need composite types to not be assignable to Personally, I don't think this is a huge problem, TBH. Note that we've been living with panics when non-comparable dynamic types are compared since Go 1.0 and I don't think it's an issue that comes up terribly often. I don't really see how this is going to be much different with the advent of generics. |
Based on the discussion above, this proposal seems like a likely decline. |
No change in consensus, so declined. |
Change https://go.dev/cl/401874 mentions this issue: |
What do I want?
comparable
type that does not includeinterface{}
.Background
#49584
comparable
type includesinterface{}
.interface{}
is passed to the function, we need to determine if it is comparable at runtime using reflect package. (to avoid panic)I think
comparable
type which can only be determined at runtime, is almost the same asany
type.generics
non-generics
The text was updated successfully, but these errors were encountered: