Branched off of  "notes on adding generics to a package", to keep separate
discussions separate:

On Mon, Feb 8, 2021 at 2:47 PM Martin Leiser <[email protected]> wrote:

> My argument is as follows: The generic package can not use any property of
> the parameter type, i.e. the interface type because of the additional
> check. The interface type by itself constrains the usage to the methods of
> the type plus assignment from any compatible type. The last property is
> taken away with the additional check.
>
And comparisons and type-assertions/switches and conversions to/from other
interface types and assignments *to* other interface types… Go's type
system just isn't simple enough that I trust simple arguments. For example,
naively it is backwards compatible to add a new field to a struct - but it
isn't
<https://blog.merovius.de/2015/07/29/backwards-compatibility-in-go.html>.

As I said, I don't have a specific breaking case in mind (for that, I also
don't understand the process you propose well enough), so you don't have to
put any stakes in this. But it just seems to encode a lot of assumptions
about Go's type system, which makes it hard to evaluate for safety.

No overloading in go up to now, how should this happen?
>

If Foo implements Bar, then `func() Foo` is not a `func() Bar` in Go. So if
you use the interface type that is being overwritten in a co- or
contravariant position, the result might break even if it's safe. The
package might, for example, implement a function that returns a local alias
to `io.Reader` and pass that to another package (which doesn't get that
override).

Again, maybe it's fine in practice. There's *probably* an argument that any
case that breaks also breaks in the type-parameter design. But in your
proposal, the person who determines which types are "parameters" is no
longer the package author. That's why I think there would really need to be
a way for the author of a package to designate what types are intended as
parameters of the package.

I have no problem adding that, it is the hook for the additional checks,
> and would improve readability. But destroies the golang 1 compatibility.
>

Not really. The Go 1 compatibility guarantee says "code that compiles and
works in Go 1.N will continue to compile and work in Go 1.(N+1)". It makes
absolutely no statement about code that uses new features from Go 1.(N+1).

Note that the contracts design even introduced a new "keyword" while
preserving compatibility, by making it context-sensitive - i.e. the parser
would treat it as an identifier, if not used in a top-level declaration.
Mechanisms like this are a kludge and we should strive to avoid them, but
there *are* ways to amend the syntax in a compatible way.

> A "struct{}" is comparable, but only to itself, not to any other type,
> including any other "struct{}" […]
>

a) Not really: https://play.golang.org/p/4MCfP8vEvdq
b) But the point is, that interface-types *are* always comparable and other
types *might not be*. So, for example, with
type X interface{}
type A struct{}
type B []byte
you have that `make(map[X]bool)` is legal, so is `make(map[S]bool)`, but
`make(map[B]bool)` is not. So your proposed property does not fully capture
the legality of instantiating an interface with a concrete type. If a
package uses X in a map or comparison, then your mechanism of rewriting the
code into using A and checking if it compiles, would say everything is
fine, but once someone tries instantiating it with B, it would fail.

So there is no clean separation between type-checking a generic package and
instantiating it. Which gets hairy, because you have to still make sure
that error messages are helpful.

> This type inference may well be added here too. But for typical container
> uses I doubt this is helpful at all. When thinking about functional
> libraries it makes more sense.
>
Also for generic algorithms (like sort or walking a graph) or (which I'm
looking forward to the most) encapsulating common concurrency idioms.

I don't mean to litigate which proposal mentions type-parameters more. But
you make it sound like putting them on types and functions means users of
generics will have to litter them everywhere. And that just doesn't seem
true at all.

> The harder stuff is the "[]interface{}" quirk of golang.
>
It's not a "quirk". It's a fundamental property of how types work
<https://blog.merovius.de/2018/06/03/why-doesnt-go-have-variance-in.html>.
There is no solution. I think it's important you understand that, because
it connects to other aspects you need to pay close attention to, when
designing generics in Go.

> Here a monomorphic implementation allows you to drop a nasty copy of a
> parameter slice with concrete types.
>
This is not a semantics-preserving transformation. It means that if the
function modifies the slice, that modification is lost. And no, you can't
work around it by copying back, because methods of the type might modify
state that is not reflected in the memory-representation of its value.

In my profesional live I am busy writing C++. completely disagree.


That's fine. As long as it's clear that to me (and perhaps others) this is
still a significant drawback of your design.

FWIW, Go is not C++. The two languages don't necessarily use the same
practices and that's fine (and indeed the reason I like Go). My personal
practice is to not factor something out into a generally useful solution,
unless I've first proven that it's *specifically* useful. i.e. I only try
to build something as a library, if I've done the same thing successfully
in a project and then realize that I need it elsewhere also.

Also, FWIW, in *my* years of writing C (before I came to Go) I certainly
used locally defined Macros a lot.

And I agree: for the discussion it is the biggest impediment, in normal
> every day coding I doubt it is a problem at all.
>

All use-cases I have for generics are motivated by normal every day coding
and none of them would be built as a library for general usage. YMMV and
that's fine. I don't intend to convince you, I'm just trying to explain why
I personally wouldn't back your proposal.

> Agree with that, but the solution suggested in the proposal would nicely
> fit here too, because it adds an new form of "interface{}" type definition,
> for this purpose. Which may be used to define named parameters as well. So
> the "Comparable" of the golang draft may well be used in my proposal
> unchanged.
>
I strongly disagree with this. `comparable` works in the type parameters
proposal, because it is only usable as a constraint.

> I know. I am way too late. Sorry for stealing your time. I only have one
> strong argument: it is a way simpler solution.
>
It might surprise you, but I disagree with this. It certainly is simpler in
the sense that it has less expressive power. But, as far as I'm concerned,
if you'd remove type-lists from the type-parameter design draft, you'd
likely get something that I would consider both simpler and more powerful -
so, if I wanted something simpler, I wouldn't go with your design, but I
would trim down the type-parameter proposal.

Any appearance of simplicity comes IMO down to a) ignoring many of the more
difficult design goals and b) asserting the existence of solutions to the
rest of more complicated problems. And personally, I just find it easier to
understand what the compiler is doing, with type-parameters on types and
functions.

Personally I think in praxis generic collections are the far more important
> aspect than functional libraries containing "Min" and "Max" functions.
>

But you can't write many generic collections without comparisons, for
example. You can't build sorted sets, without being able to order its
elements. You can't write a cycle-detection for graphs without being able
to compare nodes for equality.
FTR, I personally agree that operator-usage in generic functions shouldn't
necessarily be made a requirement (though the discussion of pointers vs.
value receivers and structural constraints in the proposal also convinced
me that type-lists are about more than just operators). But it is.

> And your writing was all about collections too.
>
I don't think so. I made very few mentions of specific use-cases - except
for `container/list`, which I used because it's the one you write about in
your design. Most of the use-cases I cant generics for are not about
containers. They are mostly about concurrency and some are just general
type-safety when passing values through APIs.

> Thank a lot for Your suggestions!
>
> Martin Leiser
>
>
> On Sun, Feb 7, 2021 at 9:20 PM Martin Leiser <[email protected]>
> wrote:
>
>> I follow the discussion about go generics for some time now, but never
>> tried using them.
>>
>> Your conclusion
>> > I struggled to grasp generics at the outset of this experiment. They
>> are complex in a way that I haven’t encountered in a while with Go: I
>> wasn’t sure when to reach for them and when to use another feature of Go.
>> is no surprise for me.
>>
>> Adopting the "c++" or "java" style of generics, which dates back to Ada
>> and experimentell languages before that is no good fit for golang in my
>> opinion. I am working on a different approach not yet published. You may
>> have a look in:
>> https://github.com/leiser1960/importbinding/blob/master/README.md
>> I do not have a "go2go" implementation for it yet. It is way simpler, and
>> there is no doubt when to reach for it.
>>
>> The basic idea is: golang already has generic types: interface types.
>> Simply constrain them to the types you actually want to use with them with.
>> It is a simple "opt in" approach. You add a type binding on import, that's
>> it. For the "generic" type in the package: Give a name to your types, which
>> helps for readability anyway.
>>
>> And big thanks for your good writeup of the experiment.
>>
>> Martin Leiser
>>
>> Ian Lance Taylor schrieb am Freitag, 29. Januar 2021 um 23:13:21 UTC+1:
>>
>>> On Fri, Jan 29, 2021 at 1:09 PM Ben Burkert <[email protected]>
>>> wrote:
>>> >
>>> > I wrote a blog post on my experience updating a package to use the
>>> > latest proposed generics feature with the go2go tool. My overall
>>> > impression is quite good as it was able to solve some existing
>>> > problems with the package. Thanks to Go team & gopher community for
>>> > all your work making generics happen!
>>> >
>>> > https://benburkert.com/posts/on-go2-generics/
>>>
>>> Thanks for the write-up!
>>>
>>> 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/1f8db11d-56a7-4f16-b6b9-7c7b0b2fe822n%40googlegroups.com
>> <https://groups.google.com/d/msgid/golang-nuts/1f8db11d-56a7-4f16-b6b9-7c7b0b2fe822n%40googlegroups.com?utm_medium=email&utm_source=footer>
>> .
>>
> --
> You received this message because you are subscribed to a topic in the
> Google Groups "golang-nuts" group.
> To unsubscribe from this topic, visit
> https://groups.google.com/d/topic/golang-nuts/Gas-PrmfknY/unsubscribe.
> To unsubscribe from this group and all its topics, send an email to
> [email protected].
> To view this discussion on the web visit
> https://groups.google.com/d/msgid/golang-nuts/CAEkBMfHT%3DkMEEqx4UTS6qojHawrNOfON72JdAckUHfzfduh3Ag%40mail.gmail.com
> <https://groups.google.com/d/msgid/golang-nuts/CAEkBMfHT%3DkMEEqx4UTS6qojHawrNOfON72JdAckUHfzfduh3Ag%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 [email protected].
> To view this discussion on the web visit
> https://groups.google.com/d/msgid/golang-nuts/3bd1da2e-091e-34ef-bec0-9631424dc089%40gmail.com
> <https://groups.google.com/d/msgid/golang-nuts/3bd1da2e-091e-34ef-bec0-9631424dc089%40gmail.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 [email protected].
To view this discussion on the web visit 
https://groups.google.com/d/msgid/golang-nuts/CAEkBMfG4pw7YjS7w6c1-Gu4bf4MPPNz6P%3D56%3DkvDqFWEEHa_EQ%40mail.gmail.com.

Reply via email to