>> On Thursday, December 31, 2020 at 11:27:06 AM UTC+1 
axel.wa...@googlemail.com wrote:
>> I don't think the current draft lets us express very powerful 
invariants. And while I wouldn't really advocate to make that a target, I 
think it would be interesting to see more discussion of this area - i.e. 
more case-studies of where Go has type-safety problems and if the current 
design can address them.

One thing that comes to mind that is not supported by the current proposal 
is the ability to express that T must be (any) struct. For example, I have 
a ORM function that scans a sql row into a struct (using reflection in its 
implementation):

// dest must be a pointer to a struct or an error is returned 
func ScanIntoStruct(row *sql.Row, dest interface{})  error {}

If you could somehow express that dest must be a pointer to a struct I 
could move one type of runtime-error into a compile-time error type (i.e. 
the purpose of generics):

// sketch code
func ScanIntoStruct[S struct](row *sql.Row, dest *S)  // NOTE: 
implementation still calls an internal function that is not generic and 
uses reflection 

Another example is where you write a library that creates an RPC service 
from any function that you provide:

func ExposeAsRPC[T func](name string, f T) {}

Again, this would then prevent ExposeASPRC to be called with anything but a 
function. Note however that the signature of f could be anything. This 
would be helpful to if you want to expose a Go function in a scripting 
language etc. 

I am not saying this a big "type-safey" problem, just an example of 
something I have encountered. 

On the other hand, I don't see a lot of cases myself where I would want to 
call some method on T in a generic function, mainly because there's already 
interfaces and helper function for this in Go if you need it.  For example, 
you could say that a generic priority queue must call a method Priority() 
on T, but that could be done in an equally type-safe way by asking for a 
helper function to be provided with T (ie. func (T) int) with the 
container.  There's the graph example in the generics proposal but I think 
that that can have a likewise type-safe solution that doesn't need the 
ability to call a method on T.  

On the other hand I agree that an "interface" in its meaning of a 
"declaration of a method set" applies equally well to compile time and 
runtime. So the current argument is (I think) that generics is just the 
application of interfaces at compile time instead of runtime. The issue I 
have with this is that it complicates (at least) the language around the 
concept of "interface" at lot (just think about all the documentation 
around interface that needs to be rewritten, and if someone asks a question 
on a interface you first need to address if it's used runtime or compile 
time, etc). A second issue is that, in my opinion, it does not agree very 
well with the idea of "one way of doing things" / orthogonality in Go (as 
explained above). 

>> The third use-case I see for generics is to catch bugs by being able to 
express more complicated type-invariants in code. An example of that would 
be type-safety for context.Value 
<https://blog.merovius.de/2020/07/20/parametric-context.html> (or, 
similarly but subtly different, optional i

The context.Value example is maybe an example of something that to me feels 
(at least initially) as a suspicious application of generics. If 
context.Context is made generic (if this is what is meant) then all 
functions that use it, such as in the sql package, are forced to be generic 
too:

    func (c *Conn) QueryContext[T any](ctx context.Context[T], query 
string, args ...interface{}) (*Rows, error) 
<https://golang.org/pkg/database/sql/#Conn.QueryContext>

Before you know it everything is generic.... On the other hand,  maybe this 
is something that you just need to get used to and be very happy with 
after. My initial reaction would be that the right choice here would be to 
make context not generic as Value is only a "extra" customer user value 
that is not part of its main functionality/purpose. However, it would 
possibly be tempting to factor interface{} into a T if you don't think too 
much about it.


-Markus


-- 
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/28dfab48-9413-4658-9272-bcc79f73153fn%40googlegroups.com.

Reply via email to