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 
> <golang-nuts@googlegroups.com> wrote:
> 
> 
>> On Tue, Jul 21, 2020 at 10:54 AM 'Javier Zunzunegui' via golang-nuts 
>> <golang-nuts@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. 
> 
> 
>>> 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.
>>>> 
>>>> -- 
>>>> 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.
>> 
>> -- 
>> 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/0a37c712-e83b-45c9-9910-12d9b40d9566n%40googlegroups.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+unsubscr...@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.

-- 
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/8E892642-F7F2-432E-9F8C-781C3419618E%40ix.netcom.com.

Reply via email to