>> 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.