Is there a way to declare a "nillable" constraint that matches all types that can be nil (pointer, slice, map, etc.) ?
I would like to write a function, that receives a parameter (with a generic type), and check if this parameter is nil.
I found a very ugly way to write it: https://go.dev/play/p/0g0SoTlBEgsThe problem: the map type needs more than 1 type, so I need to provide the 3 types when I call the `IsNil()` function/Is there a better way ?Yes I know I could use `any`, and check with reflect if the value inside the interface is nil.But I want to know if it's possible to do it with generics.Thank you.
--
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...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/golang-nuts/2043afe5-3d18-445a-90a9-75b48d3ec078n%40googlegroups.com.
Same question for `len()`: is there a way to declare a constraint that matches types that support `len()` ?
Le jeudi 22 décembre 2022 à 14:23:22 UTC+1, Pierre Durand a écrit :Is there a way to declare a "nillable" constraint that matches all types that can be nil (pointer, slice, map, etc.) ?I would like to write a function, that receives a parameter (with a generic type), and check if this parameter is nil.I found a very ugly way to write it: https://go.dev/play/p/0g0SoTlBEgsThe problem: the map type needs more than 1 type, so I need to provide the 3 types when I call the `IsNil()` function/Is there a better way ?Yes I know I could use `any`, and check with reflect if the value inside the interface is nil.But I want to know if it's possible to do it with generics.Thank you.
--
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...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/golang-nuts/5101cdb3-601a-4eec-b278-5be07a891590n%40googlegroups.com.
I want to implement a generic function to "remove nil values from a slice." This should be able to remove nil instances of error, for example.So, let's say I have:var arg = []error{nil, errors.New("oh noes"), nil}Unfortunately, this doesn't work:func Compact[T comparable](s []T) T {...if s[i] == nil {because "error" is not comparable.
This also doesn't work:func Compact[T any](s []T) T {
var zero T...if s[i] == zero {because T is not a comparable constraint.
The problem with your code is that "T comparable" guarantees that two values of type T can be compared,
--
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...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/golang-nuts/CAJgyHGPRdv%3DjOPs34V1Q%3DNh9RVpD8c-qagr%3DdEz0OX-oDEaa7Q%40mail.gmail.com.
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...
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?func Compact[T ?](sl []T) []T {j := 0for i := 0; i < len(sl); i++ {if el := sl[i]; el != nil {sl[j] = elj++}}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.)
On Tue, Oct 3, 2023 at 4:33 PM Jon Watte <jwa...@gmail.com> wrote:
>
>
>
> > 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.
Can you give us an example? There are clear reasons for being able to
compare a type to the zero value of that type. But it's not clear why
it's useful to focus on the set of types for which the zero value is
written as "nil". For example, why wouldn't I want to call your
LogJSON example with a string? Thanks.
Ian
> where it is important to permit only type arguments that can be compared to nil
I see! As in, if we somehow got a "equalszero" constraint, then that constraint would solve the problem I illustrate.I believe that assertion is correct, but I also believe that is a stronger assertion, and also that it introduces more of a new concept than a simple "nil" constraint. (Unless you're looking for some way to make "any" work, and introduce a zero keyword or something...)
--
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...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/golang-nuts/CAJgyHGPYEqrDTyRE-gMvSpiyUobHWKuL35nAAtDa1MmGd8uqzA%40mail.gmail.com.
Circling back to this, because it came up today again.Here's the generic function I want to write. It comes up in a lot of function composition, which in turn comes up in a lot of interface adapters and such:
func maybeAssign[T any](dst *T, src T, name string) {
if *dst != nil { // any can't be compared with nil
panic(fmt.Errorf("too many %s arguments", name))
}
*dst = src
}
Using this function in each assignment, instead of inlining the four-line construct with panic, can save a lot of space and make code a lot more readable.The above doesn't work, because not every type can be assigned nil.The following also doesn't work:func maybeAssign[T comparable](dst *T, src T, name string) {var zero Tif *dst != zero { // interface and other nillable types can't be compared to zero
panic(fmt.Errorf("too many %s arguments", name))
}
*dst = src
}Because interface values aren't comparable. (As aren't chans, maps, etc, but THOSE can be jammed into various interface constructs, whereas "any interface" cannot, because "interface{}" doesn't actually mean "any interface")Let me try to answer:> Why is the specific split into (interfaces, pointers, slices, functions, maps, channels) and (numbers, booleans, strings, structs, arrays) a particularly important one?Because, while go tries very hard to make sure every storable type has a "zero value," it somehow decides that you can't necessarily COMPARE to that zero value.But the whole point of zero values is that you can tell them from non-zero values!So, the language has introduced a work-around with the concept of "I can compare to nil" for these reference types that aren't comparable to their zero value.But generics don't allow us to sense or make use of this, so generics can't express what the regular language can express. Even a very simple case like the above, can't currently be expressed, and this leads to more verbose code that's harder to read and harder to work with. (Granted, this is my opinion, but I'm not alone.)
If the language instead changes so that nil means "the zero value" in general, and it so happens that these nil-comparable types can be compared to nil without any particular qualification, that also solves the problem.
That might indeed be a good solution -- but if so, it'd be nice to know what we can do to make that happen, and what the other opposition to that change might be, because that change also feels much less narrow than a "nil" type constraint.
I think "making all values comparable" is a worse change though (there's a reason they aren't comparable!)