My argument is as follows: The generic package can not use any
property of the parameter type, i.e. the interface type because of
the additional check. The interface type by itself constrains the
usage to the methods of the type plus assignment from any compatible
type. The last property is taken away with the additional check.
And comparisons and type-assertions/switches and conversions to/from other interface types and assignments *to* other interface types… Go's type system just isn't simple enough that I trust simple arguments. For example, naively it is backwards compatible to add a new field to a struct -
but it isn't.
As I said, I don't have a specific breaking case in mind (for that, I also don't understand the process you propose well enough), so you don't have to put any stakes in this. But it just seems to encode a lot of assumptions about Go's type system, which makes it hard to evaluate for safety.
No overloading in go up to now, how should this happen?
If Foo implements Bar, then `func() Foo` is not a `func() Bar` in Go. So if you use the interface type that is being overwritten in a co- or contravariant position, the result might break even if it's safe. The package might, for example, implement a function that returns a local alias to `io.Reader` and pass that to another package (which doesn't get that override).
Again, maybe it's fine in practice. There's *probably* an argument that any case that breaks also breaks in the type-parameter design. But in your proposal, the person who determines which types are "parameters" is no longer the package author. That's why I think there would really need to be a way for the author of a package to designate what types are intended as parameters of the package.
I have no problem adding that, it is the hook for the additional
checks, and would improve readability. But destroies the golang 1
compatibility.
Not really. The Go 1 compatibility guarantee says "code that compiles and works in Go 1.N will continue to compile and work in Go 1.(N+1)". It makes absolutely no statement about code that uses new features from Go 1.(N+1).
Note that the contracts design even introduced a new "keyword" while preserving compatibility, by making it context-sensitive - i.e. the parser would treat it as an identifier, if not used in a top-level declaration. Mechanisms like this are a kludge and we should strive to avoid them, but there *are* ways to amend the syntax in a compatible way.
A "struct{}" is comparable, but only to itself, not to any other
type, including any other "struct{}" […]
b) But the point is, that interface-types *are* always comparable and other types *might not be*. So, for example, with
type X interface{}
type A struct{}
type B []byte
you have that `make(map[X]bool)` is legal, so is `make(map[S]bool)`, but `make(map[B]bool)` is not. So your proposed property does not fully capture the legality of instantiating an interface with a concrete type. If a package uses X in a map or comparison, then your mechanism of rewriting the code into using A and checking if it compiles, would say everything is fine, but once someone tries instantiating it with B, it would fail.
So there is no clean separation between type-checking a generic package and instantiating it. Which gets hairy, because you have to still make sure that error messages are helpful.
This type inference may well be added here too. But for typical
container uses I doubt this is helpful at all. When thinking about
functional libraries it makes more sense.
Also for generic algorithms (like sort or walking a graph) or (which I'm looking forward to the most) encapsulating common concurrency idioms.
I don't mean to litigate which proposal mentions type-parameters more. But you make it sound like putting them on types and functions means users of generics will have to litter them everywhere. And that just doesn't seem true at all.
The harder stuff is the "[]interface{}" quirk of golang.
It's not a "quirk".
It's a fundamental property of how types work. There is no solution. I think it's important you understand that, because it connects to other aspects you need to pay close attention to, when designing generics in Go.
Here a
monomorphic implementation allows you to drop a nasty copy of a
parameter slice with concrete types.
This is not a semantics-preserving transformation. It means that if the function modifies the slice, that modification is lost. And no, you can't work around it by copying back, because methods of the type might modify state that is not reflected in the memory-representation of its value.
In my profesional live I am busy writing C++. completely disagree.
That's fine. As long as it's clear that to me (and perhaps others) this is still a significant drawback of your design.
FWIW, Go is not C++. The two languages don't necessarily use the same practices and that's fine (and indeed the reason I like Go). My personal practice is to not factor something out into a generally useful solution, unless I've first proven that it's *specifically* useful. i.e. I only try to build something as a library, if I've done the same thing successfully in a project and then realize that I need it elsewhere also.
Also, FWIW, in *my* years of writing C (before I came to Go) I certainly used locally defined Macros a lot.
And I agree: for the discussion it is the biggest impediment, in
normal every day coding I doubt it is a problem at all.
All use-cases I have for generics are motivated by normal every day coding and none of them would be built as a library for general usage. YMMV and that's fine. I don't intend to convince you, I'm just trying to explain why I personally wouldn't back your proposal.
Agree with that, but the solution suggested in the proposal would
nicely fit here too, because it adds an new form of "interface{}"
type definition, for this purpose. Which may be used to define
named parameters as well. So the "Comparable" of the golang draft
may well be used in my proposal unchanged.
I strongly disagree with this. `comparable` works in the type parameters proposal, because it is only usable as a constraint.
I know. I am way too late. Sorry for stealing your time. I only have
one strong argument: it is a way simpler solution.
It might surprise you, but I disagree with this. It certainly is simpler in the sense that it has less expressive power. But, as far as I'm concerned, if you'd remove type-lists from the type-parameter design draft, you'd likely get something that I would consider both simpler and more powerful - so, if I wanted something simpler, I wouldn't go with your design, but I would trim down the type-parameter proposal.
Any appearance of simplicity comes IMO down to a) ignoring many of the more difficult design goals and b) asserting the existence of solutions to the rest of more complicated problems. And personally, I just find it easier to understand what the compiler is doing, with type-parameters on types and functions.
Personally I think in praxis generic collections are the far more
important aspect than functional libraries containing "Min" and
"Max" functions.
But you can't write many generic collections without comparisons, for example. You can't build sorted sets, without being able to order its elements. You can't write a cycle-detection for graphs without being able to compare nodes for equality.
FTR, I personally agree that operator-usage in generic functions shouldn't necessarily be made a requirement (though the discussion of pointers vs. value receivers and structural constraints in the proposal also convinced me that type-lists are about more than just operators). But it is.
And your writing was all about collections too.
I don't think so. I made very few mentions of specific use-cases - except for `container/list`, which I used because it's the one you write about in your design. Most of the use-cases I cant generics for are not about containers. They are mostly about concurrency and some are just general type-safety when passing values through APIs.
Thank a lot for Your suggestions!
Martin Leiser
I
follow the discussion about go generics for some time now, but
never tried using them.
Your conclusion
> I struggled to grasp generics at the outset of this
experiment. They are complex in a way that I haven’t
encountered in a while with Go: I wasn’t sure when to reach
for them and when to use another feature of Go.
is no surprise for me.
I do not have a "go2go" implementation for it yet. It is
way simpler, and there is no doubt when to reach for it.
The basic idea is: golang already has generic types:
interface types. Simply constrain them to the types you
actually want to use with them with. It is a simple "opt in"
approach. You add a type binding on import, that's it. For
the "generic" type in the package: Give a name to your
types, which helps for readability anyway.
And big thanks for your good writeup of the experiment.
Martin Leiser
Ian Lance Taylor schrieb
am Freitag, 29. Januar 2021 um 23:13:21 UTC+1:
On Fri, Jan 29, 2021 at
1:09 PM Ben Burkert <b...@benburkert.com>
wrote:
>
> I wrote a blog post on my experience updating a
package to use the
> latest proposed generics feature with the go2go tool.
My overall
> impression is quite good as it was able to solve some
existing
> problems with the package. Thanks to Go team &
gopher community for
> all your work making generics happen!
>
> https://benburkert.com/posts/on-go2-generics/
Thanks for the write-up!
Ian
--
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...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/golang-nuts/1f8db11d-56a7-4f16-b6b9-7c7b0b2fe822n%40googlegroups.com.
--
You received this message because you are subscribed to a topic in
the Google Groups "golang-nuts" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/golang-nuts/Gas-PrmfknY/unsubscribe.
To unsubscribe from this group and all its topics, send an email
to golang-nuts...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/golang-nuts/CAEkBMfHT%3DkMEEqx4UTS6qojHawrNOfON72JdAckUHfzfduh3Ag%40mail.gmail.com.
--
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...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/golang-nuts/3bd1da2e-091e-34ef-bec0-9631424dc089%40gmail.com.