On Wednesday, 20 January 2021 at 03:06:43 UTC bbse...@gmail.com wrote:

> Is it possible to write a generic function that can test if its 
> argument with a constraint is nil? 
>

I think there is a deeper question in there.

In the Generics proposal, type constraints (other than type lists) take the 
form of interfaces.  For example, a generic type T may be constrained with 
interface C.

Question: if a function takes type T, does that permit *both* values of 
concrete types which implement C, *and* interface values which implement 
C?  Apparently it does:
https://go2goplay.golang.org/p/sVaW1YoXKf1

That, to me, is surprising at first.  I write a generic function because I 
want it to be expanded for different concrete types; but then I am 
surprised to find it can also be used for dynamic runtime types.

In principle, I guess it shouldn't really matter, since whatever type is 
provided has the expected behaviour.  Except: as the OP observed, interface 
types have the ability to be "nil", which concrete types don't (bar 
pointers/slices).

The end result is there's a crucial but subtle difference between:

type Foo interface { ... }
func f(v Foo) ...

and 

type Foo interface { ... }
func f[T Foo](v T) ...

Given that the second case supports both concrete types *and* interface 
types, then it seems to me that comparing a value with nil is a 
semantically valid thing to do. If the function specialisation is a 
concrete type, then that comparison would always be false and the code path 
optimised out.

Alternatively, generics could exclude interface values.  But then you get 
the weird situation that a generic function declaration that *looks* like 
an interface type, explicitly disallows interface type values!

---- 8< ----

With my wild hat on: it makes me wonder what would happen if the generics 
proposal became nothing more than interfaces with linked constraints - so 
that you could say "this function takes a function of type T (interface C) 
and returns *the same type* T", or "this function takes a []T and returns a 
value of *the same type* T".

What I mean is, the difference between
func f(a, b fmt.Stringer) c fmt.Stringer { ... }
and
func f[T fmt.Stringer](a, b T) c T { ... }
would simply be that a, b and c had to be of the *same* concrete type - but 
were otherwise still interface values (and specialisation, if implemented, 
would just be a hidden optimisation).

The obvious problem is that if you actually pass interface values around, 
then many type-mismatch violations couldn't be detected until runtime.

However: I find the same problem occurs with the current generics 
implementation, *if* you pass interface variables.  Check this out:
https://go2goplay.golang.org/p/F08gh5gotsO
Print2() expects that both arguments are of the same type - but in the 
final call, they are not!  There is neither compile-time nor run-time error.

ISTM that constrained interface types *could* also be checked at compile 
time, in the common case where the caller passes concrete types. Rewriting 
to use plain interfaces instead of generics:
https://go2goplay.golang.org/p/CfkvAcgr8mC
I think that an interface type constraint system *could* statically check 
that both args of the first Print2() call were (or were not) the same type.

What you might end up with is linked type constraints being a natural 
extension of interfaces.  Generic specialisation would just be an 
optimisation on top of that (if the call site knows that a particular set 
of concrete types is being used).  Type lists could also become an 
extension of interfaces.

However, that's just off the top of my head.  Whilst I've been following 
generics intermittently, no doubt this has been considered (and discarded) 
before.

Regards, Brian.

-- 
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/34bdb40e-ad0b-47ce-8588-d014d0886470n%40googlegroups.com.

Reply via email to