Hello, fellow Gophers!

Currently, if I understand correctly, there's no expression for the zero
value for a type variable:

type Map[K comparable, V any] struct {
    ks []K
    vs []V
}

func (m Map[K, V]) Get(k K) V {
    for i, k2 := range m.ks {
        if k2 == k {
            return m.vs[i]
        }
    }
    return zeroValue // cannot currently express this
}

This is a trivial example, but I've seen real questions about what to do in
these situations.

Currently, if I understand correctly, the only way to do this is to declare
a variable, and return that:

var zeroValue V
return zeroValue

Why not allow nil to be used as the zero value for type variables, to fill
this gap?

return nil // == V(nil)

At runtime, nil would be the zero value for the specific type argument.

Nil could actually be interpreted as the zero value for every type, even
outside of generics. The word "nil" means
<https://en.wiktionary.org/wiki/nil#Noun> zero, anyway. This would be handy
in situations where you make a type a pointer just to avoid lots of typing.
For example:

if condition1 {
    return ReallyLongStructName{}, fmt.Errorf(...)
}
if condition2 {
    return ReallyLongStructName{}, fmt.Errorf(...)
}

Instead, you could keep the non-pointer type, and then do:

if condition1 {
    return nil, fmt.Errorf(...)
}
if condition2 {
    return nil, fmt.Errorf(...)
}

It would also solidify the type abstraction concept of generic functions,
where functions varying only in concrete types can be abstracted into one
generic function with type variables. For example:

// Same implementations, different types

func (m MapIntInt) Get(k int) int {
    for i, k2 := range m.ks {
        if k2 == k {
            return m.vs[i]
        }
    }
    return nil // nil, not 0, but means the same thing for int
}

func (m MapStringString) Get(k string) string {
    for i, k2 := range m.ks {
        if k2 == k {
            return m.vs[i]
        }
    }
    return nil // nil, not "", but means the same thing for string
}

// Same implementation, abstracted types

func (m Map[K, V]) Get(k K) V {
    for i, k2 := range m.ks {
        if k2 == k {
            return m.vs[i]
        }
    }
    return nil // nil is 0 for int and "" for string
}

Similar to how generics required an inversion of the meaning of interfaces
to be type sets, perhaps generics also requires an inversion of the meaning
of zero and nil values, where every type has a nil (default) value, and for
number-like types, that just so happens to be the number zero, but for
other types, it could be whatever makes sense for them.

Anyway, I thought it was an interesting idea. Thanks for reading!

-- 
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/CAKbcuKjePVMPH1Fxv3tWAAm_msjAZKmtbJs2EMkQ7WGEgtAqyA%40mail.gmail.com.

Reply via email to