>> On Thursday, December 31, 2020 at 11:27:06 AM UTC+1
[email protected] 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 [email protected].
To view this discussion on the web visit
https://groups.google.com/d/msgid/golang-nuts/28dfab48-9413-4658-9272-bcc79f73153fn%40googlegroups.com.