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.

Reply via email to