I suggest we move the discussion about Axel's post to reddit 
<https://www.reddit.com/r/golang/comments/husc75/parametric_context/>.
Let's keep this exclusively on the the topic of embeding + generics.
For anyone joining here, the main arguments are in the 4th post here 
<https://groups.google.com/g/golang-nuts/c/v10JCQFm9_E/m/GeaWpDn-AAAJ>.
On Tuesday, July 21, 2020 at 1:45:35 PM UTC+2 ren...@ix.netcom.com wrote:

> The Context problem is more easily solved using package namespaces for 
> keys with conventions rather than type embedding. 
>
> Otherwise you end up with a brittle multiple inheritance problem. 
>
> Or you need language support for typed TLS and remove Context entirely. 
>
> On Jul 21, 2020, at 6:24 AM, 'Axel Wagner' via golang-nuts <
> golan...@googlegroups.com> wrote:
>
> 
>
> On Tue, Jul 21, 2020 at 10:54 AM 'Javier Zunzunegui' via golang-nuts <
> golan...@googlegroups.com> wrote:
>
>> It's not A(B,C,D) vs A(B(C(D))), both are supported with & without 
>> embedding. My issue is with a linked list that requires a new type for each 
>> additional node. It is potentially an explosion of types
>
>
> I don't think "explosion" is an appropriate word. It's really not any 
> worse than regular embedding. You can write `x := struct{ Y }{y}` just 
> fine, and you wouldn't say that embedding leads to "an explosion of types", 
> right? And `context.Value` also needs a new type for each value stored in 
> it, if used as recommended (for each key), and there's no "explosion of 
> types" there either.
>
> I can't think of a way you can make the number of types in a program grow 
> superlinear in code-size if we allow embedding (that we can't already do), 
> so I really don't think "explosion" is the right word - and that's 
> important, because it's indicative of there not really being a problem with 
> that
>
> an imho an abuse of the type system. 
>
>
> Potato, Tomato :) There are loads of things that are allowed and even 
> often recommended, that could very well be called an "abuse of the type 
> system". Like defining an unexported type and using it as an argument, to 
> enforce that only literals can be used. Or adding _-fields to prevent 
> comparison or copying of structs.
>
> I agree that it's probably too clever for its own good and I would prefer 
> if it were simpler. But I do think it would be very useful to have a way to 
> amend an arbitrary type with new methods without erasing any of the 
> existing ones. Context.Value was only the first example I wrote about. But 
> there are others as well, like `http.ResponseWriter`. Even an `io.Writer` 
> may benefit from being able to be wrapped without erasing potential 
> `WriteByte`, `WriteRune`, `ReadFrom`… methods.
>
> Embedding type-parameters is a way to achieve that and I don't know a 
> different way.
> I'm not saying a generics design *must* enable it, but it's certainly a 
> useful feature to have.
>  
>
>> Agreed. My point is it either ads no value, or when it does add some it 
>> is probably at the expense of things like maintainability, abstraction, 
>> tooling, types system, etc. and is simply not worth it.
>>
>
> But that's a *very different* point from your original "The fundamental 
> problem I see is it introduces complexity, but no value". Now you're simply 
> saying "it's a tradeoff and I don't think it's worth it", which is fine of 
> course :)
>
> I don't think I agree, personally. IMO it is very natural being able to do 
> this and easy enough to implement, so I don't really think the cost is 
> *that* high. And if it was *just* to do my context-experiment, I'd agree 
> that the benefit is probably too low. But as I said, a) I don't think 
> that's the only use-case and b) people *are* frequently complaining about 
> the lack of type-safety of Context.Value, so there is definitely interest 
> to solve that problem *somehow*.
>
> But ultimately, yeah. It's a tradeoff, whatever the outcome is, I'll be 
> fine :)
>
> PS I didn't find where to discuss your post in your blog. If you have 
>> somewhere for that please share and I'd be happy to discuss at more length 
>> there
>>
>
> I don't have a dedicated comment-section, because I don't want to 
> moderate. You can discuss via off-list E-Mail if you want and I also always 
> submit my posts to /r/golang 
> <https://www.reddit.com/r/golang/comments/husc75/parametric_context/>. 
>
>
> On Tuesday, July 21, 2020 at 10:15:58 AM UTC+2 axel.wa...@googlemail.com 
>> wrote:
>>
>>> Why do you feel that a type A(B, C, D, E) should be supported, but 
>>> A(B(C(D(E))) shouldn't? They are equivalent in expressiveness. And to be 
>>> clear, I'd also prefer A(B, C, D, E) for this use, but ISTM this isn't 
>>> possible without variadic type-parameters (i.e. I'd need a way to express 
>>> "this function takes a A(…) and returns an A(B,…)"). So to get this value, 
>>> you'd either need embedded type-parameters or variadic type-parameters.
>>>
>>> At the end of the day, though, my main point was "there is value". You 
>>> may very well feel that the value isn't worth the cost (as I say in the 
>>> conclusion, I'm not sure how I feel about that myself). But would you agree 
>>> that your statement "it adds complexity without adding value" doesn't 
>>> really hold up?
>>>
>>> On Tue, Jul 21, 2020 at 9:46 AM 'Javier Zunzunegui' via golang-nuts <
>>> golan...@googlegroups.com> wrote:
>>>
>>>>
>>>> Thanks for sharing Axel.
>>>>
>>>> I would place your post firmly in the category "doing something wild 
>>>> and can't use generics for it".
>>>>
>>>> Philosophical issues around context aside, it implements the chain of 
>>>> contexts directly via the type system, e.g.the TYPE after N wraps is
>>>> `FooContext(BarContext(... N times ... (context.Context))`
>>>> I would say that is abusing the type system and don't think it shuld be 
>>>> something generics should aim to support.
>>>> On Monday, July 20, 2020 at 9:54:57 PM UTC+2 axel.wa...@googlemail.com 
>>>> wrote:
>>>>
>>>>> Hi,
>>>>>
>>>>> given the discussion here, the blog post I just published might be 
>>>>> interesting:
>>>>> https://blog.merovius.de/2020/07/20/parametric-context.html
>>>>> To the best of my knowledge, what I describe there is only really 
>>>>> doable using embedded type-parameters. As I state in the conclusion, I'm 
>>>>> not entirely sure this would be something *good*. But I do think it adds 
>>>>> more type-safety and that does provide value.
>>>>>
>>>>> Interested to hear your thoughts :)
>>>>>
>>>>> Axel
>>>>>
>>>>>
>>>>> On Mon, Jul 20, 2020 at 3:37 PM 'Javier Zunzunegui' via golang-nuts <
>>>>> golan...@googlegroups.com> wrote:
>>>>>
>>>>>> Coming back at this after more thought & exploration. The fundamental 
>>>>>> problem I see is it introduces complexity, but no value.
>>>>>>
>>>>>> Say 
>>>>>> `type I interface {...}`
>>>>>> `type S(type T I) struct {T}`
>>>>>> Then the generic S (before instantiating with a particular T) may 
>>>>>> implement any interface, e.g. in any method on S or any other generic 
>>>>>> code 
>>>>>> using S, you may have
>>>>>> `_, ok := (interface{}(S(...){})` ).(Whatever)`
>>>>>> and the result of ok depends on what T is used. Without embedding, 
>>>>>> that is strue of T but not S.
>>>>>>
>>>>>> # What value did this add?
>>>>>> - You can call methods listed in I directly, e.g. if method Foo is in 
>>>>>> listed I, you can do s.Foo().
>>>>>>     => without embedding using s.I.Foo() is hardly a change.
>>>>>> - You can implement interfaces based on method listed in I directly, 
>>>>>> e.g. if method Foo is listed in I and characterises interface Fooer, you 
>>>>>> can do Fooer(s).
>>>>>>     => without embedding, you can do Fooer(s.I) or if you actually 
>>>>>> want s in the interface, write a generic method Foo in S and keep 
>>>>>> Fooer(s).
>>>>>> - You can implement interfaces based on method NOT listed in I 
>>>>>> directly, e.g. if method Foo is NOT listed in I, but is defined in some 
>>>>>> T 
>>>>>> and characterises interface Fooer, you can do Fooer(s) (for s := 
>>>>>> S(T){...}).
>>>>>>     => without embedding, you can't do this. You can do Fooer(s.I), 
>>>>>> or create a new type for this specificT,  `type X S(T)`, and implement 
>>>>>> method Foo, but let's assume that neither is acceptable. How realistic / 
>>>>>> in 
>>>>>> what circumstances do you want this? If you require a struct to have a 
>>>>>> method not listed in any contract but present in the type that happens 
>>>>>> to 
>>>>>> be embedded on this instance of the generic, and want it to be assigned 
>>>>>> to 
>>>>>> an interface that uses that method but won't accept either the embedded 
>>>>>> field in the interface, nor a separate type derived from it with the 
>>>>>> additional method, I'd say you need to re-evaluate your requirements 
>>>>>> because you are not following any moderatly sensible standards, or at 
>>>>>> the 
>>>>>> very least accept you are doing something wild and can't use generics 
>>>>>> for 
>>>>>> it.
>>>>>>
>>>>>> # What did this cost?
>>>>>> - Complexity => the possibility of there being more methods available 
>>>>>> in a struct than listed in its definition is in itself one more thing to 
>>>>>> think about.
>>>>>> - Refactoring => an embedding can't be refactored without a breacking 
>>>>>> change (can't change `type S(type T I) struct {T}` to `type S(type T I) 
>>>>>> struct {T}` + methods in I), since users may be relying on methods not 
>>>>>> present in I. 
>>>>>> - Limits to Tooling: without embedding, `_, ok := 
>>>>>> (interface{}(S(...){})` ).(Whatever)` above may always be false and the 
>>>>>> tooling may be able to identify and flag that, with embedding there is 
>>>>>> nothing it can do since it may always be true.
>>>>>>
>>>>>> # No arbitrary restrictions
>>>>>> "our hope is to make generic types work as much like ordinary types 
>>>>>> as possible, without arbitrary restrictions"
>>>>>>     => this is indeed a restriction, and I don't know how much that 
>>>>>> weights in the go team's mind regarding future features, etc. But on the 
>>>>>> other hand even allowing embedding in generics isn't quite as 
>>>>>> pre-generics 
>>>>>> go either, after all you are embedding using the generic's type name (in 
>>>>>> my 
>>>>>> example, T) and not the name of the actuall type T is instantiated with. 
>>>>>> In 
>>>>>> other words, the type produced can't be replicated without generics. 
>>>>>> Banning embedding you limit slightly the types you can produce, but at 
>>>>>> least those that are allowed are valid pre-generic go types.
>>>>>>
>>>>>> And of course there is also a 'delay decision' argument here: if 
>>>>>> embedding is banned, it can be added later. If it is allowed, the 
>>>>>> decision 
>>>>>> is final. 
>>>>>>
>>>>>> I do not claim anything dramatic about this feature's significance, 
>>>>>> like generics with fail if embedding is allowed, but also generics will 
>>>>>> not 
>>>>>> fail because they weren't. So if there is no strong reason for, and 
>>>>>> there 
>>>>>> are some reasons against, it seems to me the best decision is to ban at 
>>>>>> first and re-evaluate later.
>>>>>> On Tuesday, July 14, 2020 at 11:41:42 AM UTC+2 Javier Zunzunegui 
>>>>>> wrote:
>>>>>>
>>>>>>> Issue openned in https://github.com/golang/go/issues/40199.
>>>>>>>
>>>>>>> Still clarifying my thoughts on embedding types within generics, 
>>>>>>> will postpone this debate while I focus on other parts of the proposal 
>>>>>>> and 
>>>>>>> gain some more experience using the go2 branch. Not calling for any 
>>>>>>> action 
>>>>>>> here at this point. Thanks Ian. 
>>>>>>> On Monday, July 13, 2020 at 7:03:35 PM UTC+2 Ian Lance Taylor wrote:
>>>>>>>
>>>>>>>> On Mon, Jul 13, 2020 at 9:15 AM 'Javier Zunzunegui' via golang-nuts 
>>>>>>>> <golan...@googlegroups.com> wrote: 
>>>>>>>> > 
>>>>>>>> > In the context of Type Parameters - Draft Design#generic-types: 
>>>>>>>> > 
>>>>>>>> > Type embedding is allowed in the proposed generic changes. Oddly, 
>>>>>>>> the current implementation allows for calling methods in the embedded 
>>>>>>>> types 
>>>>>>>> but not using the method to satisfy an interface (here). That seems 
>>>>>>>> like a 
>>>>>>>> bug in the implementation. 
>>>>>>>> > 
>>>>>>>> > More significantly, it allows for calling not just the methods 
>>>>>>>> declared in the interface, but also methods available to the 
>>>>>>>> instantiated 
>>>>>>>> type but not part of the interface. Example here. I can't see what is 
>>>>>>>> the 
>>>>>>>> gain in allowing that, and it presents a risk as the interfaces 
>>>>>>>> satisfied 
>>>>>>>> by types originating from the same generic type will differ not only 
>>>>>>>> in the 
>>>>>>>> types of the methods, but also i the method names themselves. 
>>>>>>>> > 
>>>>>>>> > Would it not be best to not allow embeding in generic types? 
>>>>>>>>
>>>>>>>> At least at first glance these just seem like bugs in the current 
>>>>>>>> implementation, not in the design draft as such. Would you mind 
>>>>>>>> opening an issue for these problems? Thanks. 
>>>>>>>>
>>>>>>>> We could ban embedding type parameters, but our hope is to make 
>>>>>>>> generic types work as much like ordinary types as possible, without 
>>>>>>>> arbitrary restrictions. The existence of bugs doesn't in itself 
>>>>>>>> seem 
>>>>>>>> like a good enough reason to ban the feature. 
>>>>>>>>
>>>>>>>> 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/36bae6eb-4537-4796-8c11-60e828a36d51n%40googlegroups.com
>>>>>>  
>>>>>> <https://groups.google.com/d/msgid/golang-nuts/36bae6eb-4537-4796-8c11-60e828a36d51n%40googlegroups.com?utm_medium=email&utm_source=footer>
>>>>>> .
>>>>>>
>>>>> -- 
>>>> 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/082b29da-91ca-431f-9378-5b858727ddd3n%40googlegroups.com
>>>>  
>>>> <https://groups.google.com/d/msgid/golang-nuts/082b29da-91ca-431f-9378-5b858727ddd3n%40googlegroups.com?utm_medium=email&utm_source=footer>
>>>> .
>>>>
>>> -- 
>> 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/0a37c712-e83b-45c9-9910-12d9b40d9566n%40googlegroups.com
>>  
>> <https://groups.google.com/d/msgid/golang-nuts/0a37c712-e83b-45c9-9910-12d9b40d9566n%40googlegroups.com?utm_medium=email&utm_source=footer>
>> .
>>
> -- 
> 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/CAEkBMfHOAcmOG6Vrhn1DDYRjz%2B_KXoxqJ9Jzom65pgJxn%2BdU_g%40mail.gmail.com
>  
> <https://groups.google.com/d/msgid/golang-nuts/CAEkBMfHOAcmOG6Vrhn1DDYRjz%2B_KXoxqJ9Jzom65pgJxn%2BdU_g%40mail.gmail.com?utm_medium=email&utm_source=footer>
> .
>
>

-- 
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/3f4c1af9-e83d-4382-a41c-089a3eaf02ffn%40googlegroups.com.

Reply via email to