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 < golang-nuts@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+unsubscr...@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+unsubscr...@googlegroups.com. To view this discussion on the web visit https://groups.google.com/d/msgid/golang-nuts/CAEkBMfEVte%2Brfd89ceFGPx%2Bi0gvLa7XCuuuujgGLvV4%2BqAqLzQ%40mail.gmail.com.