On Sat, Jul 18, 2020 at 1:39 PM roger peppe <rogpe...@gmail.com> wrote:
> I didn't say there was exactly one construct for each kind of name > definition. In current Go, when a name is defined, it's defined inside a > construct that is explicitly about defining that name. By contrast, in your > proposal, we take an arbitrary type and add a dollar qualifier on a name > somewhere inside it, and that turns the construct into a definition. That > doesn't feel very Go-like to me. I think about type parameters in the same way as variables. We don't list all the variables in a function in a special list. A _value_ variable holds a number, for instance. A type parameter holds a _type_. Both variable and type parameters are declared where necessary, not upfront. Well, the parameter list of a function is an upfront list, but that's the only place. Another way to think about type parameters, let me call them also type variables, is that value variables are a run time thing while type variables exist only at compile time. Otherwise they seem pretty similar to me. > It's an arbitrary place because it's somewhere buried inside the generic type > or function. ISTM that it's not great that the form of the types or code > should > directly determine the order of the type parameters. To take an example, > say I have some code that uses some generic container defined externally: Ok, I think now I understand better. > type S struct { > container *external.Container@T1@T2 > } Note this would be invalid under the alternative proposal. The correct form would have to be: type S struct { container *external.Container@$T1@$T2 } And with the order fixing hack (Types is an example. Whatever name works, even _, but making it exported enables it to be shown in godocs): type S struct { Types [0]struct{$T1, $T2} container *external.Container@T1@T2 } > Now what if we want to change the private field to use some alternative > container implementation that happens to take > its type arguments in a different order? > > type S struct { > container *other.Container@T2@T1 > } type S struct { Types [0]struct{$T1, $T2} container *other.Container@T2@T1 } IOW, the type parameter list will in some cases appear as it does in the original proposal, just not in the prominent position. In other, possibly most cases the type parameter list is no longer needed. And let's not forget that the original draft also has its "hacks", kind of. It requires writing interface{} constraint in some cases, it requires parenthesis in other places to resolve parsing ambiguities. Both of which the alternative draft does not seem to suffer from. Compromises... >> I guess that type parameters will in practice appear most often right >> in the signature anyway. > > > I'm not keen on this rationalisation. It feels like working around something > that could have been done correctly from the outset. It's just my guess. A corpus of real existing generic Go2 code is needed to get some real numbers. > Here's another example: > > type S struct {} > > func (s S) Bz() $B { > var b B > return b > } > > func (s S) Az() $A { > var a A > return a > } > > AFAICS in this case the ordering of the methods of S influences the order of > the type parameters required to instantiate S. > If we reorder the Az and Bz methods, then we're breaking compatibility. What > if they're in different files?! You're right and this hadn't occurred to me before. The only solution I can see is: type S struct { Types [0]{$A, $B} } But I have to say that this particular example seems rather artificial to me. And maybe then the occasional Types hack does not hurt that much. After all, it then makes the alternative draft, in such cases only, become in some approximation more or less the same as the original one - with the explicit type parameter list. While substantially less verbose in other, again possibly more common cases. >> It's subjective, so saying I like it does not matter. Not sure what is >> meant by "the merging of reference and definition", can you please >> clarify? > > > I mean that we have one place that's both defining new names and acting as a > type declaration. It feels to me like you're really trying to avoid defining > the generic types as parameters, but you end up with them as implicitly > declared parameters anyway, with some additional problems picked up along the > way. I like the note from @bugpowder (another example why I see the @ sign as a natural fit) that you can think of type parameters as the property of a name like in exported vs non exported names. Exported names are also nowhere explicitly _declared_ as being exported. They are just such when they start with a capital letter in the place where they are _used_. So type parameters may be thought about like being such when they start with the $ sign. Very subjective, but it makes sense to me. Honestly, I think there's about zero chance for the alternative draft to be seriously considered by the Go team. But the discussion about it, like this one, can maybe bring some new and/or interesting views/ideas on/about the topic. Thanks to all for participating in this hopefully useful process. -- 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/CAA40n-X7Mt59HGq%2Bxq%3D2y5BzsBkXcwLit4Lx96X3c8V0RMyuDw%40mail.gmail.com.