> It's not obvious that that is an interesting set of types. How often > do people want to write a generic function that permits any type that > can be compared to nil but does not permit any numeric or string type?
Well I've run into this with some frequency, and a bunch of other developers here have similarly moaned that this is a big gaping hole in the constraint system. So, at least from our corner of the world, this is a legitimate desire. There's a few other questions like this on the internet, too, so I don't think "we" are particularly special. > Unless I misunderstand, you seem to have shifted the goal a bit. > There is currently no way to restrict a type argument to be an > interface type, with or without your suggestion of a nil constraint. I have not shifted the goal. This very function has been my particular goal in this thread from the start, because it clearly illustrates the need for this constraint. The only reason any other possible solution (like "zero values") was suggested in this thread, was as a possible work-around for the lack of a `nil` constraint. (Note that this particular function could usefully be applied to slices of maps, slices of chans, and so on -- none of which are comparable.) "assign to nil" is also pretty useful as a generic constraint, because that also includes "return a nil literal." This can combo nicely with some other interfaces, such as JSON or YAML or protobuf marshaling/demarshaling. So, for illustration: func LogJSON[T nil](name string, arg T) { if arg == nil { Log(name, "is empty") } else { data := Infallible(json.Marshal(arg)) Log(name, string(data)) } } (The actual, production uses of these kinds of affordances are typically a little more involved, but we would save a lot of boilerplate/repeated code if this constraint were available.) (Also, Infallible() could be a good standard library function, because it's common enough, but that's a totally different discussion that's not related here.) Sincerely, Jon Watte -- "I find that the harder I work, the more luck I seem to have." -- Thomas Jefferson On Tue, Oct 3, 2023 at 12:32 PM Ian Lance Taylor <i...@golang.org> wrote: > On Tue, Oct 3, 2023 at 12:06 PM Jon Watte <jwa...@gmail.com> wrote: > > > > I don't want to include int or struct{} in this case. I care > specifically about "can be compared to nil" > > The only thing I can do with a type parameter that is only constrained > as "nil" is compare it to nil, or assign nil to it. > > This means approximately "any reference type" -- interfaces, pointers, > maps, slices, chans... > > It's not obvious that that is an interesting set of types. How often > do people want to write a generic function that permits any type that > can be compared to nil but does not permit any numeric or string type? > > > > But, let's put this out there: > > How would you, today, write a function that compacted a slice of > interface, such that any "nil" interface value would be removed from the > slice? > > Unless I misunderstand, you seem to have shifted the goal a bit. > There is currently no way to restrict a type argument to be an > interface type, with or without your suggestion of a nil constraint. > > > > func Compact[T ?](sl []T) []T { > > j := 0 > > for i := 0; i < len(sl); i++ { > > if el := sl[i]; el != nil { > > sl[j] = el > > j++ > > } > > } > > return sl[:j] > > } > > > > There's nothing today I can put in place of the "?" to make this > perfectly-reasonable generic function work. > > I propose I should be able to put "nil" in place of the "?" to make this > work, and it would work for any reference type (that can be compared or > assigned to nil.) > > > > Unless I'm missing something? > > Well, here is a version that works for a slice of any type, including > an interface type. Arguably, though, using reflect is cheating. > > func Compact[T any](s []T) []T { > j := 0 > for _, v := range s { > vv := reflect.ValueOf(v) > if vv.IsValid() && !vv.IsZero() { > s[j] = v > j++ > } > } > return s[:j] > } > > Ian > -- 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/CAJgyHGPBPnVaXoJT%2BYD0XYA9CS7TxqyOZJ_bjoz_9w59v-FhEA%40mail.gmail.com.