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
> <[email protected]> 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 [email protected].
To view this discussion on the web visit
https://groups.google.com/d/msgid/golang-nuts/87caf8c4-1523-48f2-8d3f-0b5fe6c5361cn%40googlegroups.com.