I was planning to read the updated proposal in more details before 
replying, but I haven't been able to find the time sadly, so I'm doing it 
anyway :), mostly inline.  There are a couple of general points I'd like to 
put forward first.

- What I'm trying to push towards is not my particular approach, but more 
simplicity while retaining enough usefulness (that is, being a good fit for 
the established good use cases for generics in Go).  I think that when you 
explore how to introduce generics into Go, it's important to remember how 
effective it has been without generics (and partly because of its lack of 
generics), and to try not to upset that balance.

- There is one aspect of the current proposal that makes me think that we 
can find a better manifestation of generics in Go.  To take the one of the 
simplest examples, the Stringer example:

type Stringer interface {
String() string
}

Here is the generic Stringify implementation

func Stringify(type T Stringer)(s []T) (ret []string) {
for _, v := range s {
ret = append(ret, v.String())
}
return ret
}

Here is the "plain" non-generic one

func Stringify(s []Stringer) (ret []string) {
for _, v := range s {
ret = append(ret, v.String())
}
return ret
}

The two implementations above express the same intent, even have the same 
body, but they are not the same thing!  Obviously you can use 
Stringify(Stringer) to obtain the second one from the first but to me it 
feels like we are missing a trick, a better perspective that would make 
this simplest of examples more natural.

- shortly after the contracts proposal was published, I found that I was 
unhappy with the overlap between contracts and interfaces, wrote an 
explanation of the problem and imagined a rebalancing of the proposal which 
is in essence the new one (ie. interfaces can be generic).  I think it's 
useful because it presents a rationale for "transforming" the earlier 
contracts proposal into the new interface-based one, so I've posted it 
here: 
https://arnodel.github.io/marooned/go/generics/2020/06/21/go-against-contracts.html

Kind regards,

Arnaud Delobelle

On Wednesday, 17 June 2020 at 06:10:08 UTC+1 Ian Lance Taylor wrote:

> On Tue, Jun 16, 2020 at 1:54 PM Arnaud Delobelle 
> <arnaud.d...@sparx.co.uk> wrote: 
> > 
> > I noticed today the blog post about the revised Generics proposal. What 
> got me excited is this extract at the start: 
> > 
> > The biggest change is that we are dropping the idea of contracts. The 
> difference between contracts and interface types was confusing, so we’re 
> eliminating that difference. 
> > 
> > To me the lack of orthogonality between contracts and interfaces was the 
> major issue with the previous proposal and I have been musing with ways of 
> resolving it for a while, so I am very pleased that the proposal is going 
> down this path! 
> > 
> > Last month I decided to write a post about a way of introducing Generics 
> into Go using interfaces, which I called "Package Specialization". 
> > 
> > Headline features are: 
> > 
> > use interfaces to express parametric types; 
> > no new keyword; 
> > the only new syntax is “package specialization”: pkg(T=int, 
> Y=*MyType).Func(); 
> > generic code which doesn’t use the package specialization syntax is 
> already valid Go. 
> > 
> > The full post can be read here: 
> https://arnodel.github.io/marooned/go/generics/2020/06/06/go-spec2.html 
> > 
> > I was toying with the idea of submitting it here for feedback, to try to 
> move the discussion in that direction. Well, I guess today's updated 
> proposal steals my thunder! Essentially this is the same idea, but with a 
> different manifestation in the language - I thought that submitting it 
> anyway may provide a useful comparison point to help gauge the updated 
> proposal better. 
> > 
> > Note that sadly, I do not have much time to polish a proposal or to 
> follow discussions in general on this or other golang-related discussion 
> lists, so I apologize in advance if I am inadvertently re-hashing ideas 
> that have been put forward and dismissed in the past, or if my blog post is 
> a little low on detail (it was meant to be an exploration of a possible 
> approach). 
>
> Thanks. I hadn't seen that before. 
>
> A difficulty with package specialization is when you want to write a 
> List(List(int)). That is, a List where each element of the List is a 
> List(int). 


That would be

     list(T = list(T = int).List).List,

which I agree is not the most palatable.  Of course one could defined an 
intermediary type

  type intList = list(T = int).List
 

> Or, when you want to write a transformation function as in 
>
> https://go.googlesource.com/proposal/+/refs/heads/master/design/go2draft-type-parameters.md#list-transform.
>  
>
>

I guess to do it literally you would do something like this.

package transform

type T1 interface {}
type T2 interface {}
func Transform(lst *list(T1).List, f func(T1) T2) *list(T2).List {
ret := &list(T2){}
it := lst.Range()
for {
if v, ok := it.Val(); ok {
ret.Push(f(v))
}
if !it.Next() {
break
}
}
return ret
}

To me it becomes apparent that it's not the right way of doing this though 
as the implementation of Transform doesn't really depend on the fact that 
we are dealing with lists, instead it relies solely on the iteration 
interface for the source and the "pushing" interface for the destination.  
So I'd probably have it as something like:

--- transform/transform.go ---
package transform

type T1 interface{}
type T2 interface{}

type S interface {
    Next() bool
    Val() (T1, bool)
}

type D interface {
    Push(T2)
}

func Transform(src S, f func(T1) T2, dst D) {
    for {
        if v, ok := src.Val(); ok {
            dst.Push(v)
        }
        if !src.Next() {
            return
        }
    }
}

--- main.go ---
// l1 is a list of ints
l2 := &list(float64).List{}
transform(...).Transform(l1.Range(), l2, func(n int) float64 { return 
float64(n)})

That transform package doesn't require special generic syntax to be written 
(or understood), and I guess that was part of my aim.


It would seem to require some modification of how imports work in Go, 
> and that leads into considerable complexity. See also 
> .
> https://go.googlesource.com/proposal/+/refs/heads/master/design/go2draft-type-parameters.md#why-not-put-type-parameters-on-packages
>  
>

I must admit that although I do know how imports work in Go, I don't know 
anything about how they are implemented.  I did try to think this through 
though and outlined a way to understand the semantics of specialized 
packages, which I thought was acceptable.  To me there are also interesting 
questions about importing "generic entities" and specializing them with the 
same types in different packages under the current proposal (but I haven't 
been able to verify what the proposed solution to these issues are).

> . 
>
> 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/87caf8c4-1523-48f2-8d3f-0b5fe6c5361cn%40googlegroups.com.

Reply via email to