Oh (sorry, being forgetful) and re "it's less of a new mechanism than
introducing a zero identifier": #62487
<https://github.com/golang/go/issues/62487> introduces *even less* new
mechanism, by expanding comparison to (and assignment of) `nil` to all
types inside a generic function. It's not a new class of constraint, it
just special-cases `nil` a bit more. So it is still a far more general
mechanism, that solves more problems than `nilable` constraint, while
requiring fewer (or at worst the same number of) new concepts.

On Wed, Oct 4, 2023 at 7:36 AM Axel Wagner <axel.wagner...@googlemail.com>
wrote:

> (correction: It should be Convert[J isinterface, T J]. I changed the name
> from I to J to be more readable and then missed one occurrence)
>
> On Wed, Oct 4, 2023 at 7:33 AM Axel Wagner <axel.wagner...@googlemail.com>
> wrote:
>
>> On Wed, Oct 4, 2023 at 6:54 AM Jon Watte <jwa...@gmail.com> wrote:
>>
>>> > 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...)
>>>
>>
>> Yes, that is what #61372 <https://go.dev/issue/61372> proposes:
>> Introduce a `zero` predeclared identifier (!) that is assignable to any
>> type and comparable to any type. With some discussion about whether it
>> should only apply inside generic code or not. There is no proposal (as far
>> as I know) for anything like an "equalszero" constraint, as every type can
>> be assigned a meaningful comparison to its zero value, so it seems we
>> should just allow it for all types.
>>
>> To be clear, the criticism of a `nilable` constraint is
>> 1. It only solves a subset of the problem we are seeing. You gave
>> examples from that subset. I gave some examples of problems we are seeing
>> that are *not* in that subset.
>> 2. It is not really clear this particular subset is particularly
>> important. Why is the *specific* split into (interfaces, pointers,
>> slices, functions, maps, channels) and (numbers, booleans, strings,
>> structs, arrays) a particularly important one?
>> 3. As long as that is not clear, it seems more prudent to focus on
>> mechanisms that solve more of the problems we are seeing.
>>
>> FWIW I could, personally, get more (though still not fully) on board with
>> an `isinterface` constraint, that would allow *only* interfaces. It
>> would still allow assignment and comparison to `nil`. But it seems far
>> clearer to me, that interfaces can be singled out. While a `nil` interface
>> is categorically an invalid value, the same is not true for `nil`
>> pointers/maps/channels/funcs *in general*. Any of those kinds of types
>> could still have methods callable on them that work perfectly fine (by
>> doing an `if receiver == nil` check in the method). You categorically can't
>> call a method on a `nil` interface.
>>
>> And an `isinterface` constraint could still conceivable be useful for
>> many of the examples you mentioned. Or it would allow
>>
>> func Convert[J isinterface, T I](s []T) []J {
>>     out := make([]I, len(T))
>>     for i, v := range s {
>>         out[i] = J(v)
>>     }
>>     return out
>> }
>>
>> I'd still not be convinced this is really worth it, but at least it seems
>> clearer why that particular subset of types deserves to be singled out. In
>> fact, many people have argued that the interface zero value really
>> shouldn't have been spelled `nil`, because interfaces have so little in
>> common, conceptually, to other "nilable" types.
>>
>>
>>>
>>> Also, there's the ergonomics of having to make a zero value instance.
>>> Maybe we can rely on the compiler to optimize it away, but at a minimum it
>>> adds another required line of code in the implementation. E g:
>>>
>>> func MaybeNuke[T nil](b bool, val T) T {
>>>   if b {
>>>     return nil
>>>   }
>>>   return val
>>> }
>>>
>>> func MaybeNuke(T zero](b bool, val T) T {
>>>   if b {
>>>     var nope T // an extra line!
>>>     return nope
>>>   }
>>>   return val
>>> }
>>>
>>> func MaybeNuke(T any](b bool, val T) T {
>>>   if b {
>>>     return zero[T]{} // maybe? seems weird
>>>   }
>>>   return val
>>> }
>>>
>>> This is because not all zero values can be instantiated inline with
>>> simply T{}.
>>>
>>> Sincerely,
>>>
>>> Jon Watte
>>>
>>>
>>> --
>>> "I find that the harder I work, the more luck I seem to have." --
>>> Thomas Jefferson
>>>
>>

-- 
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/CAEkBMfHx5pvp3uezJhJAprT2M_7QpYi87%2BrLXnTfQoEweTv54A%40mail.gmail.com.

Reply via email to